Skip to content

Commit 0e675b4

Browse files
committed
Preserve supplied environment casing
1 parent 0d459e6 commit 0e675b4

7 files changed

Lines changed: 16 additions & 12 deletions

File tree

.agents/skills/exceptionless-javascript/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Use this skill to produce source-accurate setup code, integration guidance, and
99

1010
Keep answers compact. Prefer pointing to official docs for broad product behavior, and use local package READMEs/source to correct stale snippets or repo-specific package details.
1111

12-
Deployment environments use `config.environment` or `config.setEnvironment(name)` as the default, and `builder.setEnvironment(name)` for overrides. They serialize as top-level `environment`, separately from `data.@environment`. See [configuration.md](references/configuration.md).
12+
Deployment environments use `config.environment` or `config.setEnvironment(name)` as the default, and `builder.setEnvironment(name)` for overrides. They serialize as top-level `environment`, separately from `data.@environment`, preserving the supplied casing after trimming. See [configuration.md](references/configuration.md).
1313

1414
## Official Docs
1515

.agents/skills/exceptionless-javascript/references/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ await Exceptionless.startup((config) => {
3131

3232
## Deployment environment
3333

34-
Set `config.environment = "production"` or call `config.setEnvironment("production")`. Per-event `setEnvironment("staging")` overrides the default. Names are trimmed and lowercased; empty names, names longer than 64 characters, and control characters are ignored. Missing values remain unspecified. This property is independent of `data.@environment` runtime metadata and of the application version. It does not change server stack grouping or create per-environment status.
34+
Set `config.environment = "production"` or call `config.setEnvironment("production")`. Per-event `setEnvironment("staging")` overrides the default. Names are trimmed and retain their supplied casing; empty names, names longer than 64 characters, and control characters are ignored. Missing values remain unspecified. The server filters case-insensitively and normalizes aggregation keys. This property is independent of `data.@environment` runtime metadata and of the application version. It does not change server stack grouping or create per-environment status.
3535

3636
## Privacy
3737

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The definition of the word exceptionless is: to be without exception. Exceptionl
88

99
## Browser
1010

11-
Set a deployment environment in startup configuration with `config.environment = "production"` (or `config.setEnvironment("production")`). Override it on an event with `Exceptionless.createLog("Example").setEnvironment("staging").submit()`. Names are trimmed, lowercased, and limited to 64 characters. Missing or invalid names remain unspecified. The top-level `environment` is separate from machine/runtime diagnostics in `data.@environment`; stacks and fixed versions remain shared across environments.
11+
Set a deployment environment in startup configuration with `config.environment = "production"` (or `config.setEnvironment("production")`). Override it on an event with `Exceptionless.createLog("Example").setEnvironment("staging").submit()`. Names are trimmed and limited to 64 characters, preserving the supplied casing. The server filters case-insensitively and normalizes aggregation keys. Missing or invalid names remain unspecified. The top-level `environment` is separate from machine/runtime diagnostics in `data.@environment`; stacks and fixed versions remain shared across environments.
1212

1313
You can install the npm package via `npm install @exceptionless/browser --save`
1414
or via cdn [`https://unpkg.com/@exceptionless/browser`](https://unpkg.com/@exceptionless/browser).

packages/core/src/Utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ export function normalizeEnvironment(value: string | null | undefined): string |
563563
if (typeof value !== "string") {
564564
return undefined;
565565
}
566-
const name = value.trim().toLowerCase();
566+
const name = value.trim();
567567
// eslint-disable-next-line no-control-regex -- Deployment names cannot contain control characters.
568568
return name && name.length <= 64 && !/[\u0000-\u001f\u007f-\u009f]/u.test(name) ? name : undefined;
569569
}

packages/core/test/configuration/Configuration.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { describe, expect, test } from "vitest";
33
import { Configuration } from "../../src/configuration/Configuration.js";
44

55
describe("Configuration", () => {
6-
test("should normalize deployment environments and allow clearing the default", () => {
6+
test("should trim deployment environments, preserve casing, and allow clearing the default", () => {
77
const config = new Configuration();
88
expect(config.environment).toBeUndefined();
99
config.setEnvironment(" Production ");
10-
expect(config.environment).toBe("production");
10+
expect(config.environment).toBe("Production");
1111
config.environment = "Staging";
12-
expect(config.environment).toBe("staging");
12+
expect(config.environment).toBe("Staging");
13+
config.environment = "İ".repeat(64);
14+
expect(config.environment).toBe("İ".repeat(64));
1315
config.setEnvironment("");
1416
expect(config.environment).toBeUndefined();
1517
config.setEnvironment("x".repeat(65));

packages/core/test/plugins/default/ConfigurationDefaultsPlugin.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ describe("ConfigurationDefaultsPlugin", () => {
1414
for (const type of ["error", "log", "usage", "session"]) {
1515
const event: Event = { type, data: { "@environment": { machine_name: "worker-1" } } };
1616
await plugin.run(new EventPluginContext(client, event, new EventContext()));
17-
expect(event.environment).toBe("production");
17+
expect(event.environment).toBe("Production");
1818
expect(event.data?.["@environment"]?.machine_name).toBe("worker-1");
1919
}
2020

2121
const builder = client.createLog("test", "message").setEnvironment(" Staging ");
2222
await plugin.run(new EventPluginContext(client, builder.target, new EventContext()));
23-
expect(builder.target.environment).toBe("staging");
24-
expect(JSON.parse(JSON.stringify(builder.target)).environment).toBe("staging");
23+
expect(builder.target.environment).toBe("Staging");
24+
expect(JSON.parse(JSON.stringify(builder.target)).environment).toBe("Staging");
2525
});
2626

27-
test.each(["", " ", "x".repeat(65), "prod\ninvalid", "İ".repeat(64)])("should keep invalid override %j unspecified", async (environment) => {
27+
test.each(["", " ", "x".repeat(65), "prod\ninvalid"])("should keep invalid override %j unspecified", async (environment) => {
2828
const client = new ExceptionlessClient();
2929
client.config.environment = "production";
3030
const builder = client.createLog("test", "message").setEnvironment(environment);

packages/core/test/plugins/default/DuplicateCheckerPlugin.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,16 @@ describe("DuplicateCheckerPlugin", () => {
8686

8787
test("should merge duplicates only within the same environment", async () => {
8888
const enqueue = vi.spyOn(client.config.services.queue, "enqueue");
89+
expect((await run(Exception1StackTrace, "Production")).cancelled).not.toBe(true);
8990
expect((await run(Exception1StackTrace, "production")).cancelled).not.toBe(true);
9091
expect((await run(Exception1StackTrace, "staging")).cancelled).not.toBe(true);
9192
expect((await run(Exception1StackTrace)).cancelled).not.toBe(true);
93+
expect((await run(Exception1StackTrace, "Production")).cancelled).toBe(true);
9294
expect((await run(Exception1StackTrace, "production")).cancelled).toBe(true);
9395
expect((await run(Exception1StackTrace, "staging")).cancelled).toBe(true);
9496
expect((await run(Exception1StackTrace)).cancelled).toBe(true);
9597
await plugin.suspend();
96-
expect(enqueue.mock.calls.map(([event]) => event.environment).sort()).toEqual(["production", "staging", undefined]);
98+
expect(enqueue.mock.calls.map(([event]) => event.environment).sort()).toEqual(["Production", "production", "staging", undefined]);
9799
});
98100

99101
test("should ignore error without stack", async () => {

0 commit comments

Comments
 (0)