Repository: awslabs/aws-embedded-metrics-node (ts)

Issue:
 Allow namespace to be specifiable via environment variables
See also: https://github.com/awslabs/aws-embedded-metrics-python/issues/15

Pull request description:
Allow setting namespace via an environment variable
*Issue #, if available:*
Closed #39

*Description of changes:*
Allows setting namespace via the AWS_EMF_NAMESPACE environment variable or via the configuration object

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.


Patch:
diff --git a/README.md b/README.md
index d368ef6..933abab 100644
--- a/README.md
+++ b/README.md
@@ -311,6 +311,24 @@ Configuration.debuggingLoggingEnabled = true;
 AWS_EMF_ENABLE_DEBUG_LOGGING=true
 ```
 
+**Namespace**: Sets the CloudWatch [namespace](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Namespace) that extracted metrics should be published to. If not set, a default value of aws-embedded-metrics will be used.
+
+Requirements:
+
+- Name Length 1-255 characters
+- Name must be ASCII characters only
+
+Example:
+
+```js
+// in process
+const { Configuration } = require("aws-embedded-metrics");
+Configuration.namespace = "Namespace";
+
+// environment
+AWS_EMF_NAMESPACE=Namespace
+```
+
 ## Examples
 
 Check out the [examples](https://github.com/awslabs/aws-embedded-metrics-node/tree/master/examples) directory to get started.
diff --git a/src/config/EnvironmentConfigurationProvider.ts b/src/config/EnvironmentConfigurationProvider.ts
index b3f5137..9a431e0 100644
--- a/src/config/EnvironmentConfigurationProvider.ts
+++ b/src/config/EnvironmentConfigurationProvider.ts
@@ -14,6 +14,7 @@
  */
 
 import { IConfiguration } from './IConfiguration';
+import { Constants } from '../Constants';
 import Environments from '../environment/Environments';
 
 const ENV_VAR_PREFIX = 'AWS_EMF';
@@ -26,6 +27,7 @@ enum ConfigKeys {
   SERVICE_TYPE = 'SERVICE_TYPE',
   AGENT_ENDPOINT = 'AGENT_ENDPOINT',
   ENVIRONMENT_OVERRIDE = 'ENVIRONMENT',
+  NAMESPACE = 'NAMESPACE',
 }
 
 export class EnvironmentConfigurationProvider {
@@ -40,6 +42,7 @@ export class EnvironmentConfigurationProvider {
       serviceType:
         this.getEnvVariable(ConfigKeys.SERVICE_TYPE) || this.getEnvVariableWithoutPrefix(ConfigKeys.SERVICE_TYPE),
       environmentOverride: this.getEnvironmentOverride(),
+      namespace: this.getEnvVariable(ConfigKeys.NAMESPACE) || Constants.DEFAULT_NAMESPACE,
     };
   }
 
diff --git a/src/config/IConfiguration.ts b/src/config/IConfiguration.ts
index 37391f1..8b46fb9 100644
--- a/src/config/IConfiguration.ts
+++ b/src/config/IConfiguration.ts
@@ -57,4 +57,9 @@ export interface IConfiguration {
    * - EC2: decorates logs with EC2 metadata and sends over TCP
    */
   environmentOverride: Environments | undefined;
+
+  /**
+   * Sets the CloudWatch namespace that extracted metrics should be published to.
+   */
+  namespace: string;
 }
diff --git a/src/logger/MetricsContext.ts b/src/logger/MetricsContext.ts
index 3f40127..430c179 100644
--- a/src/logger/MetricsContext.ts
+++ b/src/logger/MetricsContext.ts
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-import { Constants } from '../Constants';
+import Configuration from '../config/Configuration';
 import { LOG } from '../utils/Logger';
 import { MetricValues } from './MetricValues';
 import { Unit } from './Unit';
@@ -57,7 +57,7 @@ export class MetricsContext {
     dimensions?: Array<Record<string, string>>,
     defaultDimensions?: Record<string, string>,
   ) {
-    this.namespace = namespace || Constants.DEFAULT_NAMESPACE;
+    this.namespace = namespace || Configuration.namespace
     this.properties = properties || {};
     this.dimensions = dimensions || [];
     this.meta.Timestamp = new Date().getTime();


Test patch:
diff --git a/src/config/__tests__/EnvironmentConfigurationProvider.test.ts b/src/config/__tests__/EnvironmentConfigurationProvider.test.ts
index 6c29648..496a20f 100644
--- a/src/config/__tests__/EnvironmentConfigurationProvider.test.ts
+++ b/src/config/__tests__/EnvironmentConfigurationProvider.test.ts
@@ -207,3 +207,39 @@ test('if environment override cannot be parsed, default to unknown', () => {
   const result = config.environmentOverride;
   expect(result).toBe(Environments.Unknown);
 });
+
+test('namespace defaults to aws-embedded-metrics', () => {
+  // act
+  const config = getConfig();
+
+  // assert
+  const result = config.namespace;
+  expect(result).toBe('aws-embedded-metrics');
+});
+
+test('can set namespace from environment', () => {
+  // arrange
+  const expectedValue = faker.random.word();
+  process.env.AWS_EMF_NAMESPACE = expectedValue;
+
+  // act
+  const config = getConfig();
+
+  // assert
+  const result = config.namespace;
+  expect(result).toBe(expectedValue);
+});
+
+test('can manually set namespace', () => {
+  // arrange
+  const expectedValue = faker.random.word();
+  process.env.AWS_EMF_NAMESPACE = faker.random.word();
+  const config = getConfig();
+
+  // act
+  config.namespace = expectedValue;
+
+  // assert
+  const result = config.namespace;
+  expect(result).toBe(expectedValue);
+});