Make ready for release 2.3.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19202dd..cb34e7b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,23 @@
 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [2.3.0] - 2022-03-18
+
+### Added
+
+- Metrics (the meter name is 'DotPulsar')
+    - dotpulsar.client.count - number of active clients (gauge)
+    - dotpulsar.connection.count - number of active connections (gauge)
+    - dotpulsar.reader.count - number of active readers (gauge with 'topic' tag)
+    - dotpulsar.consumer.count - number of active consumers (gauge with 'topic' tag)
+    - dotpulsar.producer.count - number of active producers (gauge with 'topic' tag)
+    - dotpulsar.producer.send.duration - Measures the duration for sending a message (histogram with 'topic' tag)
+    - dotpulsar.consumer.process.duration - Measures the duration for processing a message (histogram with 'topic' and 'subscription' tags)
+
+### Changed
+
+- Adding a property to MessageMetadata with a key or value of null will throw an ArgumentNullException
+
 ## [2.2.0] - 2022-02-04
 
 ### Added
diff --git a/README.md b/README.md
index 499b68c..d031189 100644
--- a/README.md
+++ b/README.md
@@ -48,8 +48,7 @@
 - [X] Service discovery
 - [X] Automatic reconnect
 - [X] TLS connections
-- [X] TLS Authentication
-- [X] JSON Web Token Authentication
+- [X] Pulsar Proxy
 - [X] Producer send with custom metadata
 - [X] Producer send with event time, sequence id, and delayed message delivery
 - [X] Producer send with key and ordering key
@@ -62,11 +61,18 @@
 - [X] Consume compacted topics
 - [X] Reader API
 - [X] Read/Consume/Acknowledge batched messages
-- [X] Pulsar Proxy
-- [X] [LZ4 message compression](https://github.com/apache/pulsar-dotpulsar/wiki/Compression)
-- [X] [ZLIB message compression](https://github.com/apache/pulsar-dotpulsar/wiki/Compression)
-- [X] [ZSTD message compression](https://github.com/apache/pulsar-dotpulsar/wiki/Compression)
-- [X] [SNAPPY message compression](https://github.com/apache/pulsar-dotpulsar/wiki/Compression)
+- [X] Telemetry
+    - [Tracing](https://github.com/apache/pulsar-dotpulsar/wiki/Tracing)
+    - [Metrics](https://github.com/apache/pulsar-dotpulsar/wiki/Metrics)
+- [X] Authentication
+    - TLS Authentication
+    - JSON Web Token Authentication
+    - Custom Authentication
+- [X] [Message compression](https://github.com/apache/pulsar-dotpulsar/wiki/Compression)
+    - LZ4
+    - ZLIB
+    - ZSTD
+    - SNAPPY
 - [X] Schemas
     - Boolean
     - Bytes (using byte[] and ReadOnlySequence\<byte\>)
diff --git a/src/DotPulsar/DotPulsar.csproj b/src/DotPulsar/DotPulsar.csproj
index 42b77af..2a80124 100644
--- a/src/DotPulsar/DotPulsar.csproj
+++ b/src/DotPulsar/DotPulsar.csproj
@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0</TargetFrameworks>
-    <Version>2.2.0</Version>
+    <Version>2.3.0</Version>
     <AssemblyVersion>$(Version)</AssemblyVersion>
     <FileVersion>$(Version)</FileVersion>
     <Authors>ApachePulsar,DanskeCommodities,dblank</Authors>
diff --git a/src/DotPulsar/Internal/DotPulsarMeter.cs b/src/DotPulsar/Internal/DotPulsarMeter.cs
index db0e525..e56d6a2 100644
--- a/src/DotPulsar/Internal/DotPulsarMeter.cs
+++ b/src/DotPulsar/Internal/DotPulsarMeter.cs
@@ -37,11 +37,11 @@
     static DotPulsarMeter()
     {
         Meter = new(Constants.ClientName, Constants.ClientVersion);
-        var numberOfClients = Meter.CreateObservableGauge("dotpulsar.client.count", GetNumberOfClients, "{clients}", "Number of clients");
-        var numberOfConnections = Meter.CreateObservableGauge("dotpulsar.connection.count", GetNumberOfConnections, "{connections}", "Number of connections");
-        var numberOfReaders = Meter.CreateObservableGauge("dotpulsar.reader.count", GetNumberOfReaders, "{readers}", "Number of readers");
-        var numberOfConsumers = Meter.CreateObservableGauge("dotpulsar.consumer.count", GetNumberOfConsumers, "{consumers}", "Number of consumers");
-        var numberOfProducers = Meter.CreateObservableGauge("dotpulsar.producer.count", GetNumberOfProducers, "{producers}", "Number of producers");
+        _ = Meter.CreateObservableGauge("dotpulsar.client.count", GetNumberOfClients, "{clients}", "Number of clients");
+        _ = Meter.CreateObservableGauge("dotpulsar.connection.count", GetNumberOfConnections, "{connections}", "Number of connections");
+        _ = Meter.CreateObservableGauge("dotpulsar.reader.count", GetNumberOfReaders, "{readers}", "Number of readers");
+        _ = Meter.CreateObservableGauge("dotpulsar.consumer.count", GetNumberOfConsumers, "{consumers}", "Number of consumers");
+        _ = Meter.CreateObservableGauge("dotpulsar.producer.count", GetNumberOfProducers, "{producers}", "Number of producers");
         _producerSendDuration = Meter.CreateHistogram<double>("dotpulsar.producer.send.duration", "ms", "Measures the duration for sending a message");
         _consumerProcessDuration = Meter.CreateHistogram<double>("dotpulsar.consumer.process.duration", "ms", "Measures the duration for processing a message");
     }
diff --git a/src/DotPulsar/Internal/Producer.cs b/src/DotPulsar/Internal/Producer.cs
index c45d118..91fd6a5 100644
--- a/src/DotPulsar/Internal/Producer.cs
+++ b/src/DotPulsar/Internal/Producer.cs
@@ -244,6 +244,7 @@
             metadata.SequenceId = _sequenceId.FetchNext();
 
         var activity = DotPulsarActivitySource.StartProducerActivity(metadata, _operationName, _activityTags);
+        var startTimestamp = DotPulsarMeter.MessageSentEnabled ? Stopwatch.GetTimestamp() : 0;
 
         try
         {
@@ -251,8 +252,6 @@
             var producer = _producers[partition];
             var data = _options.Schema.Encode(message);
 
-            var startTimestamp = DotPulsarMeter.MessageSentEnabled ? Stopwatch.GetTimestamp() : 0;
-
             var messageId = await producer.Send(metadata.Metadata, data, cancellationToken).ConfigureAwait(false);
 
             if (startTimestamp != 0)