diff --git a/doc/BuiltInMetrics.md b/doc/BuiltInMetrics.md index 103b790e76f..7a8a29d3b09 100644 --- a/doc/BuiltInMetrics.md +++ b/doc/BuiltInMetrics.md @@ -54,7 +54,7 @@ instance_number | A Guid representing the current runtime. On restart, all metri | `edgeAgent_command_latency_seconds` | `command` | How long it took docker to execute the given command. Possible commands are: create, update, remove, start, stop, restart | Gauge | | `edgeAgent_iothub_syncs_total` | | The amount of times edgeAgent attempted to sync its twin with iotHub, both successful and unsuccessful. This incudes both agent requesting a twin and hub notifying of a twin update | Counter | | `edgeAgent_unsuccessful_iothub_syncs_total` | | The amount of times edgeAgent failed to sync its twin with iotHub. | Counter | -| `edgeAgent_deployment_time_seconds` | | The amount of time it took to complete a new deployment after recieving a change. | Counter | +| `edgeAgent_deployment_time_seconds` | | The amount of time it took to complete a new deployment after receiving a change. | Counter | | `edgeagent_direct_method_invocations_count` | `method_name` | Number of times a built-in edgeAgent direct method is called, such as Ping or Restart. | Counter | ||| | `edgeAgent_host_uptime_seconds` || How long the host has been on | Gauge | @@ -65,7 +65,7 @@ instance_number | A Guid representing the current runtime. On restart, all metri | `edgeAgent_total_memory_bytes` | `module_name` | RAM available | Gauge | | `edgeAgent_used_cpu_percent` | `module_name` | Percent of cpu used by all processes | Histogram | | `edgeAgent_created_pids_total` | `module_name` | The number of processes or threads the container has created | Gauge | -| `edgeAgent_total_network_in_bytes` | `module_name` | The amount of bytes recieved from the network | Gauge | +| `edgeAgent_total_network_in_bytes` | `module_name` | The amount of bytes received from the network | Gauge | | `edgeAgent_total_network_out_bytes` | `module_name` | The amount of bytes sent to network | Gauge | | `edgeAgent_total_disk_read_bytes` | `module_name` | The amount of bytes read from the disk | Gauge | | `edgeAgent_total_disk_write_bytes` | `module_name` | The amount of bytes written to disk | Gauge | diff --git a/doc/[Old]Metrics.md b/doc/[Old]Metrics.md deleted file mode 100644 index 0780e712815..00000000000 --- a/doc/[Old]Metrics.md +++ /dev/null @@ -1,133 +0,0 @@ - -# **!!! IMPORTANT NOTE !!! The metrics described here were removed in release 1.1.0. They are superseded by [edge metrics V2](BuiltInMetrics.md).** - -## Metrics in EdgeHub - -EdgeHub is intrumented to collect the following metrics: - -| MetricName | Description | Unit | -| ------------- |:-------------:|:-----:| -| EdgeHubToCloudMessageLatencyMs | Time taken by EdgeHub to send a message to the cloud | Milliseconds** | -| EdgeHubToCloudMessageSentCount | Number of messages sent by EdgeHub to the cloud | Count resets each reporting interval* | -| EdgeHubConnectedClientGauge | Number of clients/devices currently connected to EdgeHub | Count | -| EndpointMessageStoredLatencyMs | Time taken by EdgeHub to acknowledge receipt of a message | Milliseconds** | -| EndpointMessageStoredCount | Total number of messages stored by EdgeHub | Last recorded total | -| EndpointMessageDrainedCount | Total number of messages sent to a message endpoint by EdgeHub | Last recorded total | -| MessageEntityStorePutOrUpdateLatencyMs | Time taken by EdgeHub to record a message in an internal reference counting db store | Milliseconds** | -| SequentialStoreAppendLatencyMs | Time taken by EdgeHub to store a message in an append log | Milliseconds** | -| DbGetLatencyMs | Time taken by EdgeHub to get a message from the store-and-forward db | Milliseconds** | -| DbPutLatencyMs | Time taken by EdgeHub to write a message to the store-and-forward db | Milliseconds** | - -\* EdgeHub reports metrics to InfluxDb every 5s. Counters are reset after each reporting interval so that if the time series is summed up over a large interval, it returns the true sum as opposed to a sum of sums. - -\** Latency measurements are recorded per operation being measured. The Edge runtime does not aggregate measurements. The measurements are reported to InfluxDb at a regular interval, currently set to 5s. Aggregations can be done via queries from the database. - -## Configuring EdgeHub to record metrics - -EdgeHub can be configured to record metrics by setting an environment variable called **'CollectMetrics'** to **'true'**. -This can be done via the portal in the 'Configure advanced Edge Runtime settings' section. If CollectMetrics is set to true, the default -storage location for metrics is an InfluxDb container running on the same docker network as EdgeHub. - -The following defaults can be modified by setting environment variables in EdgeHub: - -| Environment variable | Description | Default | -|----------------------|:-----------:|:--------:| -| Metrics__MetricsDbName | Name of metrics database in InfluxDb | metricsdatabase | -| Metrics__InfluxDbUrl | Network address of InfluxDb | http://influxdb:8086 | - -## Creating a deployment for metrics collection - -Besides setting the EdgeHub environment variables as described in the previous section, an InfluxDb container needs to be added to the -deployment as a module with the following configuration: - -``` -"influxdb": { - "type": "docker", - "settings": { - "image": "registry.hub.docker.com/library/influxdb:latest", - "createOptions": "" - }, - "version": "1.0", - "status": "running", - "restartPolicy": "always" -} -``` -## Viewing metrics from EdgeHub - -Metrics captured by EdgeHub can be viewed using Chronograf (https://www.influxdata.com/time-series-platform/chronograf/). A Chronograf module can be -added to the deployment with the following parameters: - -``` -"chronograf": { - "type": "docker", - "settings": { - "image": "registry.hub.docker.com/library/chronograf:latest", - "createOptions": "{\r\n \"PortBindings\": {\r\n \"8888/tcp\": [\r\n {\r\n \"HostPort\": \"8888\"\r\n }]\r\n }\r\n}" - }, - "status": "running", - "restartPolicy": "always", - "version": "1.0" -} -``` -After the modules are deployed, Chronograf can be reached at http://localhost:8888. InfluxDb should be configured as a data source for Chronograf. The InfluxDb instance should be reachable at http://influxdb:8086. - -## Example InfluxDb queries - -For example InfluxDb queries, please look at https://github.com/Azure/iotedge/blob/master/tools/snitch/snitcher/src/settings.yaml#L16 - -## Collecting CPU and memory stats from EdgeHub and other containers - -A telegraf container can be added to the deployment to collect stats about all containers in the deployment. Telegraf uses a configuration file on the device to configure itself. Azure IoT Edge deployments can only mount files in to a container but cannot pass a configuration file to the device from the cloud. For this reason, the configuration has to be done on the device as follows: -``` -mkdir telegraf -docker run --rm telegraf telegraf config > telegraf/telegraf.conf -``` -Edit the file to reflect the following changes: -``` -[[outputs.influxdb]] - urls = ["http://influxdb:8086"] -[[inputs.docker]] - endpoint = "unix:///var/run/docker.sock" -``` -The telegraf container can be run manually on the device as follows: -``` -docker run -d --name=telegraf --net=azure-iot-edge -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro telegraf -``` -Or the container can be added to an Azure IoT Edge deployment using the following deployment information: -``` -"telegraf": { - "type": "docker", - "settings": { - "image": "registry.hub.docker.com/library/telegraf:latest", - "createOptions": "{\"HostConfig\":{\"Binds\":[\"/var/run/docker.sock:/var/run/docker.sock\",\"/home/jadsa/telegraf/telegraf.conf:/etc/telegraf/telegraf.conf\"]}}" - }, - "version": "1.0", - "status": "running", - "restartPolicy": "always" -} -``` -After telegraf is running on the device it will emit metrics about the docker containers. These metrics can be viewed in Chronograf under the telegraf.autogen metrics database. -More details on telegraf docker images can be found at https://hub.docker.com/_/telegraf/. - -## Setting up alerts - -Alerts can be setup using the Kapacitor component of the TICK stack. Kapacitor can be run manually on the device as follows: -``` -mkdir kapacitor -docker run --rm kapacitor kapacitord config > kapacitor/kapacitor.conf -docker run -d --name=kapacitor --net=azure-iot-edge -p 9092:9092 -v $PWD/kapacitor/kapacitor.conf:/etc/kapacitor/kapacitor.conf:ro kapacitor -``` -Alternatively, the container can be run via an Azure IoT Edge deployment using the following deployment information: -``` -"kapacitor": { - "type": "docker", - "settings": { - "image": "registry.hub.docker.com/library/kapacitor:latest", - "createOptions": "{\"HostConfig\":{\"Binds\":[\"/home/jadsa/kapacitor/kapacitor.conf:/etc/kapacitor/kapacitor.conf\"]}}" - }, - "status": "running", - "restartPolicy": "always", - "version": "1.0" -} -``` -Details on setting up alerts using Kapacitor can be found at https://docs.influxdata.com/kapacitor/v1.5/working/kapa-and-chrono/. More details on kapacitor docker images can be found at https://hub.docker.com/_/kapacitor/. diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs index 142b8697ef8..bcc8732e5e7 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs @@ -146,6 +146,11 @@ public async Task ReconcileAsync(CancellationToken token) if (plan.IsEmpty) { + if (this.currentConfig.Version != deploymentConfigInfo.Version) + { + await this.UpdateCurrentConfig(deploymentConfigInfo); + } + this.status = DeploymentStatus.Success; } else diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/AgentTests.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/AgentTests.cs index dfecb156b97..07129dacace 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/AgentTests.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/AgentTests.cs @@ -129,6 +129,8 @@ public async void ReconcileAsyncOnEmptyPlan() .ReturnsAsync(ImmutableDictionary.Empty); mockPlanner.Setup(pl => pl.PlanAsync(It.Is(ms => ms.Equals(desiredModuleSet)), currentModuleSet, runtimeInfo, ImmutableDictionary.Empty)) .Returns(Task.FromResult(Plan.Empty)); + mockReporter.Setup(r => r.ReportAsync(token, It.IsAny(), It.IsAny(), It.IsAny(), DeploymentStatus.Success)) + .Returns(Task.CompletedTask); var agent = new Agent(mockConfigSource.Object, mockEnvironmentProvider.Object, mockPlanner.Object, mockPlanRunner.Object, mockReporter.Object, mockModuleIdentityLifecycleManager.Object, configStore, DeploymentConfigInfo.Empty, serde, encryptionDecryptionProvider, availabilityMetric); @@ -136,7 +138,7 @@ public async void ReconcileAsyncOnEmptyPlan() mockEnvironment.Verify(env => env.GetModulesAsync(token), Times.Once); mockPlanner.Verify(pl => pl.PlanAsync(It.Is(ms => ms.Equals(desiredModuleSet)), currentModuleSet, runtimeInfo, ImmutableDictionary.Empty), Times.Once); - mockReporter.Verify(r => r.ReportAsync(token, currentModuleSet, runtimeInfo, DeploymentConfigInfo.Empty.Version, DeploymentStatus.Success), Times.Once); + mockReporter.Verify(r => r.ReportAsync(token, currentModuleSet, runtimeInfo, deploymentConfigInfo.Version, DeploymentStatus.Success), Times.Once); mockPlanRunner.Verify(r => r.ExecuteAsync(1, Plan.Empty, token), Times.Never); } diff --git a/mqtt/mqtt-bridge/src/persist/loader.rs b/mqtt/mqtt-bridge/src/persist/loader.rs index 990a8ae96e3..4e3eca90597 100644 --- a/mqtt/mqtt-bridge/src/persist/loader.rs +++ b/mqtt/mqtt-bridge/src/persist/loader.rs @@ -199,7 +199,7 @@ mod tests { // add many elements let mut state_lock = state.lock(); - let num_elements = 10 as usize; + let num_elements = 10_usize; for i in 0..num_elements { #[allow(clippy::cast_possible_truncation)] let key = Key { offset: i as u64 }; diff --git a/mqtt/mqtt-bridge/src/persist/waking_state/mod.rs b/mqtt/mqtt-bridge/src/persist/waking_state/mod.rs index 598946fb5f6..5dbb13dae43 100644 --- a/mqtt/mqtt-bridge/src/persist/waking_state/mod.rs +++ b/mqtt/mqtt-bridge/src/persist/waking_state/mod.rs @@ -68,7 +68,7 @@ mod tests { #[test_case(WakingMemoryStore::default())] fn ordering_maintained_across_insert(mut state: impl StreamWakeableState) { // insert a bunch of elements - let num_elements = 10 as usize; + let num_elements = 10_usize; for i in 0..num_elements { #[allow(clippy::cast_possible_truncation)] let key = Key { offset: i as u64 }; @@ -94,7 +94,7 @@ mod tests { #[test_case(WakingMemoryStore::default())] async fn ordering_maintained_across_removal(mut state: impl StreamWakeableState) { // insert a bunch of elements - let num_elements = 10 as usize; + let num_elements = 10_usize; for i in 0..num_elements { #[allow(clippy::cast_possible_truncation)] let key = Key { offset: i as u64 }; @@ -247,6 +247,10 @@ mod tests { } #[test_case(WakingMemoryStore::default())] + // TODO: There is a clippy bug where it shows false positive for this rule. + // When this issue is closed remove this allow. + // https://github.com/rust-lang/rust-clippy/issues/6353 + #[allow(clippy::await_holding_refcell_ref)] async fn insert_wakes_stream(state: impl StreamWakeableState + Send + 'static) { // setup data let state = Rc::new(RefCell::new(state)); diff --git a/mqtt/mqtt-broker/src/persist.rs b/mqtt/mqtt-broker/src/persist.rs index 78d039c2e3f..96f4edbe8d1 100644 --- a/mqtt/mqtt-broker/src/persist.rs +++ b/mqtt/mqtt-broker/src/persist.rs @@ -8,7 +8,6 @@ use std::{ error::Error as StdError, fs::{self, OpenOptions}, io::{Read, Write}, - iter::FromIterator, path::PathBuf, }; @@ -307,8 +306,8 @@ where { let payloads = HashMap::>::deserialize(deserializer)? .into_iter() - .map(|(k, v)| (k, Bytes::from(v))); - let payloads = HashMap::from_iter(payloads); + .map(|(k, v)| (k, Bytes::from(v))) + .collect(); Ok(payloads) } diff --git a/mqtt/mqtt3/src/proto/packet.rs b/mqtt/mqtt3/src/proto/packet.rs index 23ee44308e1..5dc80aead0e 100644 --- a/mqtt/mqtt3/src/proto/packet.rs +++ b/mqtt/mqtt3/src/proto/packet.rs @@ -179,7 +179,7 @@ impl PacketMeta for Connect { let client_id = super::Utf8StringDecoder::default() .decode(&mut src)? .ok_or(super::DecodeError::IncompletePacket)?; - let client_id = if client_id == "" { + let client_id = if client_id.is_empty() { if connect_flags & 0x02 == 0 { return Err(super::DecodeError::ConnectZeroLengthIdWithExistingSession); }