nestjs-otel
Version:
NestJS OpenTelemetry Library
145 lines (144 loc) • 5.95 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
const common_1 = require("@nestjs/common");
const api_1 = require("@opentelemetry/api");
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
const wide_event_context_1 = require("./wide-event.context");
const wide_event_field_decorator_1 = require("./wide-event-field.decorator");
const TestDecoratorThatSetsMetadata = () => (0, common_1.SetMetadata)("some-metadata", true);
class TestService {
countBooks() {
return 3;
}
async countBooksAsync() {
return 5;
}
createOrder() {
return { total: 42.5 };
}
createOrderWithFailingPick() {
return { total: 42.5 };
}
createObjectWithoutPick() {
return { total: 42.5 };
}
metadata() {
return 1;
}
createInvalidArray() {
return [{ id: 1 }];
}
}
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("books.count"),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestService.prototype, "countBooks", null);
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("books.count"),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], TestService.prototype, "countBooksAsync", null);
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("order.total", (order) => order.total),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestService.prototype, "createOrder", null);
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("order.total", () => {
throw new Error("pick failed");
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestService.prototype, "createOrderWithFailingPick", null);
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("order"),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestService.prototype, "createObjectWithoutPick", null);
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("books.count"),
TestDecoratorThatSetsMetadata(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestService.prototype, "metadata", null);
__decorate([
(0, wide_event_field_decorator_1.WideEventField)("items"),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestService.prototype, "createInvalidArray", null);
describe("WideEventField", () => {
let instance;
let bag;
let provider;
const withBag = (fn) => api_1.context.with(api_1.context.active().setValue(wide_event_context_1.WIDE_EVENT_CONTEXT_KEY, bag), fn);
beforeAll(() => {
provider = new sdk_trace_node_1.NodeTracerProvider();
provider.register();
});
afterAll(async () => {
await provider.shutdown();
});
beforeEach(() => {
instance = new TestService();
bag = new Map();
});
it("should record the return value of a sync method", () => {
const result = withBag(() => instance.countBooks());
expect(result).toBe(3);
expect(bag.get("books.count")).toBe(3);
});
it("should record the resolved value of an async method", async () => {
const result = await withBag(() => instance.countBooksAsync());
expect(result).toBe(5);
expect(bag.get("books.count")).toBe(5);
});
it("should record the picked value", () => {
const result = withBag(() => instance.createOrder());
expect(result).toEqual({ total: 42.5 });
expect(bag.get("order.total")).toBe(42.5);
});
it("should not break the method when pick throws", () => {
const result = withBag(() => instance.createOrderWithFailingPick());
expect(result).toEqual({ total: 42.5 });
expect(bag.size).toBe(0);
});
it("should skip values that are not valid attribute values", () => {
const result = withBag(() => instance.createObjectWithoutPick());
expect(result).toEqual({ total: 42.5 });
expect(bag.has("order")).toBe(false);
});
it("should skip arrays containing non-primitive elements", () => {
const result = withBag(() => instance.createInvalidArray());
expect(result).toEqual([{ id: 1 }]);
expect(bag.has("items")).toBe(false);
});
it("should be a no-op outside a wide event request", () => {
const result = instance.countBooks();
expect(result).toBe(3);
expect(bag.size).toBe(0);
});
it("should preserve the original method name", () => {
expect(instance.countBooks.name).toBe("countBooks");
});
it("should maintain reflect metadata", () => {
expect(Reflect.getMetadata("some-metadata", instance.metadata)).toBe(true);
});
});