@uploadista/observability 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.turbo/turbo-build.log +19 -2
  2. package/dist/index.cjs +1 -0
  3. package/dist/index.d.cts +736 -0
  4. package/dist/index.d.cts.map +1 -0
  5. package/dist/index.d.ts +735 -7
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -14
  8. package/dist/index.js.map +1 -0
  9. package/package.json +4 -3
  10. package/tsdown.config.ts +11 -0
  11. package/dist/core/errors.d.ts +0 -8
  12. package/dist/core/errors.d.ts.map +0 -1
  13. package/dist/core/errors.js +0 -108
  14. package/dist/core/index.d.ts +0 -8
  15. package/dist/core/index.d.ts.map +0 -1
  16. package/dist/core/index.js +0 -8
  17. package/dist/core/layers.d.ts +0 -104
  18. package/dist/core/layers.d.ts.map +0 -1
  19. package/dist/core/layers.js +0 -110
  20. package/dist/core/logging.d.ts +0 -18
  21. package/dist/core/logging.d.ts.map +0 -1
  22. package/dist/core/logging.js +0 -41
  23. package/dist/core/metrics.d.ts +0 -37
  24. package/dist/core/metrics.d.ts.map +0 -1
  25. package/dist/core/metrics.js +0 -72
  26. package/dist/core/testing.d.ts +0 -43
  27. package/dist/core/testing.d.ts.map +0 -1
  28. package/dist/core/testing.js +0 -93
  29. package/dist/core/tracing.d.ts +0 -19
  30. package/dist/core/tracing.d.ts.map +0 -1
  31. package/dist/core/tracing.js +0 -43
  32. package/dist/core/utilities.d.ts +0 -11
  33. package/dist/core/utilities.d.ts.map +0 -1
  34. package/dist/core/utilities.js +0 -41
  35. package/dist/flow/errors.d.ts +0 -15
  36. package/dist/flow/errors.d.ts.map +0 -1
  37. package/dist/flow/errors.js +0 -66
  38. package/dist/flow/index.d.ts +0 -6
  39. package/dist/flow/index.d.ts.map +0 -1
  40. package/dist/flow/index.js +0 -6
  41. package/dist/flow/layers.d.ts +0 -40
  42. package/dist/flow/layers.d.ts.map +0 -1
  43. package/dist/flow/layers.js +0 -94
  44. package/dist/flow/metrics.d.ts +0 -52
  45. package/dist/flow/metrics.d.ts.map +0 -1
  46. package/dist/flow/metrics.js +0 -89
  47. package/dist/flow/testing.d.ts +0 -11
  48. package/dist/flow/testing.d.ts.map +0 -1
  49. package/dist/flow/testing.js +0 -27
  50. package/dist/flow/tracing.d.ts +0 -35
  51. package/dist/flow/tracing.d.ts.map +0 -1
  52. package/dist/flow/tracing.js +0 -42
  53. package/dist/service/metrics.d.ts +0 -23
  54. package/dist/service/metrics.d.ts.map +0 -1
  55. package/dist/service/metrics.js +0 -17
  56. package/dist/storage/azure.d.ts +0 -47
  57. package/dist/storage/azure.d.ts.map +0 -1
  58. package/dist/storage/azure.js +0 -89
  59. package/dist/storage/filesystem.d.ts +0 -47
  60. package/dist/storage/filesystem.d.ts.map +0 -1
  61. package/dist/storage/filesystem.js +0 -70
  62. package/dist/storage/gcs.d.ts +0 -47
  63. package/dist/storage/gcs.d.ts.map +0 -1
  64. package/dist/storage/gcs.js +0 -90
  65. package/dist/storage/index.d.ts +0 -5
  66. package/dist/storage/index.d.ts.map +0 -1
  67. package/dist/storage/index.js +0 -5
  68. package/dist/storage/s3.d.ts +0 -47
  69. package/dist/storage/s3.d.ts.map +0 -1
  70. package/dist/storage/s3.js +0 -67
  71. package/dist/test-observability.d.ts +0 -12
  72. package/dist/test-observability.d.ts.map +0 -1
  73. package/dist/test-observability.js +0 -153
  74. package/dist/upload/errors.d.ts +0 -16
  75. package/dist/upload/errors.d.ts.map +0 -1
  76. package/dist/upload/errors.js +0 -107
  77. package/dist/upload/index.d.ts +0 -6
  78. package/dist/upload/index.d.ts.map +0 -1
  79. package/dist/upload/index.js +0 -6
  80. package/dist/upload/layers.d.ts +0 -32
  81. package/dist/upload/layers.d.ts.map +0 -1
  82. package/dist/upload/layers.js +0 -63
  83. package/dist/upload/metrics.d.ts +0 -46
  84. package/dist/upload/metrics.d.ts.map +0 -1
  85. package/dist/upload/metrics.js +0 -80
  86. package/dist/upload/testing.d.ts +0 -32
  87. package/dist/upload/testing.d.ts.map +0 -1
  88. package/dist/upload/testing.js +0 -52
  89. package/dist/upload/tracing.d.ts +0 -25
  90. package/dist/upload/tracing.d.ts.map +0 -1
  91. package/dist/upload/tracing.js +0 -35
@@ -1,153 +0,0 @@
1
- /**
2
- * Validation test for core observability infrastructure
3
- *
4
- * This test validates:
5
- * 1. Layer creation and composition
6
- * 2. Storage observability with metrics
7
- * 3. Error classification
8
- * 4. Tracing with spans
9
- * 5. Structured logging
10
- */
11
- import { Effect, Metric } from "effect";
12
- import { classifyStorageError, createStorageMetrics, makeStorageObservabilityLayer, StorageObservability, trackStorageError, withStorageSpan, logStorageOperation, logUploadCompletion, } from "./index.js";
13
- // ============================================================================
14
- // Test: Create Storage Observability Layer
15
- // ============================================================================
16
- const testStorageType = "test-s3";
17
- const testMetrics = createStorageMetrics(testStorageType);
18
- const TestStorageObservabilityLayer = makeStorageObservabilityLayer(testStorageType, testMetrics, true);
19
- // ============================================================================
20
- // Test: Simulate Upload Operation with Full Observability
21
- // ============================================================================
22
- const simulateUpload = (fileSize, shouldFail) => Effect.gen(function* () {
23
- const obs = yield* StorageObservability;
24
- console.log(`\n📊 Testing with storage type: ${obs.storageType}`);
25
- console.log(`Service: ${obs.serviceName}`);
26
- console.log(`Enabled: ${obs.enabled}`);
27
- // Log operation start
28
- yield* logStorageOperation(testStorageType, "uploadFile", "test-upload-123", { file_size: fileSize });
29
- // Simulate upload with tracing
30
- const uploadEffect = Effect.gen(function* () {
31
- // Track upload request
32
- yield* obs.metrics.uploadRequestsTotal.pipe(Metric.tagged("upload_id", "test-upload-123"))(Effect.succeed(1));
33
- // Track file size
34
- yield* obs.metrics.fileSizeHistogram(Effect.succeed(fileSize));
35
- // Simulate upload work
36
- yield* Effect.sleep("100 millis");
37
- if (shouldFail) {
38
- return yield* Effect.fail(new Error("NetworkError: Connection timeout"));
39
- }
40
- // Track success
41
- yield* obs.metrics.uploadSuccessTotal.pipe(Metric.tagged("upload_id", "test-upload-123"))(Effect.succeed(1));
42
- return { uploadId: "test-upload-123", key: "test-file.jpg" };
43
- });
44
- // Wrap with span
45
- const result = yield* uploadEffect.pipe(withStorageSpan("uploadFile", testStorageType, {
46
- "file.size": fileSize,
47
- "upload.id": "test-upload-123",
48
- }));
49
- // Log completion
50
- yield* logUploadCompletion(testStorageType, "test-upload-123", {
51
- fileSize,
52
- totalDurationMs: 100,
53
- throughputBps: (fileSize / 100) * 1000,
54
- });
55
- return result;
56
- });
57
- // ============================================================================
58
- // Test: Error Classification
59
- // ============================================================================
60
- const testErrorClassification = Effect.gen(function* () {
61
- console.log("\n🔍 Testing Error Classification:");
62
- const testErrors = [
63
- { error: { code: "NetworkError" }, expected: "network_error" },
64
- { error: { code: "InvalidAccessKeyId" }, expected: "authentication_error" },
65
- { error: { code: "AccessDenied" }, expected: "authorization_error" },
66
- { error: { code: "SlowDown" }, expected: "throttling_error" },
67
- { error: { code: "InternalError" }, expected: "server_error" },
68
- { error: { code: "InvalidRequest" }, expected: "client_error" },
69
- { error: { code: "UnknownError" }, expected: "unknown_error" },
70
- ];
71
- for (const { error, expected } of testErrors) {
72
- const category = classifyStorageError(error);
73
- const status = category === expected ? "✅" : "❌";
74
- console.log(` ${status} ${error.code} -> ${category} (expected: ${expected})`);
75
- }
76
- });
77
- // ============================================================================
78
- // Test: Error Tracking with Metrics
79
- // ============================================================================
80
- const testErrorTracking = Effect.gen(function* () {
81
- const obs = yield* StorageObservability;
82
- console.log("\n⚠️ Testing Error Tracking:");
83
- const error = new Error("ECONNRESET: Connection reset by peer");
84
- error.code = "ECONNRESET";
85
- yield* trackStorageError(testStorageType, obs.metrics, "uploadPart", error, { upload_id: "test-upload-456", part_number: 1 });
86
- console.log(" ✅ Error tracked with metrics and logs");
87
- });
88
- // ============================================================================
89
- // Test: Successful Upload Flow
90
- // ============================================================================
91
- const testSuccessfulUpload = Effect.gen(function* () {
92
- console.log("\n✅ Testing Successful Upload:");
93
- const result = yield* simulateUpload(1024 * 1024 * 10, false); // 10MB file
94
- console.log(` ✅ Upload completed: ${result.uploadId} -> ${result.key}`);
95
- });
96
- // ============================================================================
97
- // Test: Failed Upload Flow
98
- // ============================================================================
99
- const testFailedUpload = Effect.gen(function* () {
100
- console.log("\n❌ Testing Failed Upload:");
101
- const obs = yield* StorageObservability;
102
- // Use either to handle success and failure cases
103
- const result = yield* Effect.either(simulateUpload(1024 * 1024 * 5, true));
104
- if (result._tag === "Left") {
105
- const error = result.left;
106
- const errorMsg = error instanceof Error ? error.message : String(error);
107
- console.log(` ❌ Upload failed as expected: ${errorMsg}`);
108
- // Track the error
109
- yield* trackStorageError(testStorageType, obs.metrics, "uploadFile", error, { upload_id: "test-upload-789" });
110
- console.log(" ✅ Error handled and tracked successfully");
111
- }
112
- else {
113
- console.log(" ❌ Upload should have failed but succeeded");
114
- }
115
- });
116
- // ============================================================================
117
- // Test: Metrics Snapshot
118
- // ============================================================================
119
- const testMetricsSnapshot = Effect.gen(function* () {
120
- console.log("\n📈 Testing Metrics Snapshot:");
121
- const snapshot = yield* Metric.snapshot;
122
- console.log(` ✅ Captured ${snapshot.length} metric(s)`);
123
- // Display some metrics
124
- for (const metric of snapshot.slice(0, 5)) {
125
- console.log(` - ${metric.metricKey.name}: ${JSON.stringify(metric.metricState)}`);
126
- }
127
- });
128
- // ============================================================================
129
- // Run All Tests
130
- // ============================================================================
131
- const runTests = Effect.gen(function* () {
132
- console.log("🧪 Observability Infrastructure Validation Test");
133
- console.log("=".repeat(50));
134
- // Run all tests
135
- yield* testErrorClassification;
136
- yield* testSuccessfulUpload;
137
- yield* testFailedUpload;
138
- yield* testErrorTracking;
139
- yield* testMetricsSnapshot;
140
- console.log("\n" + "=".repeat(50));
141
- console.log("✅ All tests completed successfully!");
142
- console.log("\nCore observability infrastructure is working correctly:");
143
- console.log(" ✅ Layer creation and composition");
144
- console.log(" ✅ Metrics tracking (counters, histograms, gauges)");
145
- console.log(" ✅ Error classification and tracking");
146
- console.log(" ✅ Tracing with spans");
147
- console.log(" ✅ Structured logging");
148
- }).pipe(Effect.provide(TestStorageObservabilityLayer));
149
- // Run the tests
150
- Effect.runPromise(runTests).catch((error) => {
151
- console.error("\n❌ Test failed:", error);
152
- process.exit(1);
153
- });
@@ -1,16 +0,0 @@
1
- import { Effect } from "effect";
2
- import type { UploadServerMetrics } from "./metrics.js";
3
- export type UploadErrorCategory = "network_error" | "authentication_error" | "authorization_error" | "validation_error" | "size_limit_error" | "storage_error" | "abort_error" | "unknown_error";
4
- /**
5
- * Classify upload errors into standard categories
6
- */
7
- export declare const classifyUploadError: (error: unknown) => UploadErrorCategory;
8
- /**
9
- * Track upload errors with metrics and structured logging
10
- */
11
- export declare const trackUploadError: (metrics: UploadServerMetrics, operation: string, error: unknown, context?: Record<string, unknown>) => Effect.Effect<void, never, never>;
12
- /**
13
- * Create a custom error classifier for upload operations
14
- */
15
- export declare const createUploadErrorClassifier: (customErrorMapping?: (error: unknown) => UploadErrorCategory | null) => (error: unknown) => UploadErrorCategory;
16
- //# sourceMappingURL=errors.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/upload/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAMxD,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,sBAAsB,GACtB,qBAAqB,GACrB,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,aAAa,GACb,eAAe,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,mBAqFpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC3B,SAAS,mBAAmB,EAC5B,WAAW,MAAM,EACjB,OAAO,OAAO,EACd,UAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,sCAiCnC,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,qBAAqB,CAAC,KAAK,EAAE,OAAO,KAAK,mBAAmB,GAAG,IAAI,MAE3D,OAAO,OAAO,KAAG,mBAU1B,CAAC"}
@@ -1,107 +0,0 @@
1
- import { Effect, Metric } from "effect";
2
- /**
3
- * Classify upload errors into standard categories
4
- */
5
- export const classifyUploadError = (error) => {
6
- if (!error || typeof error !== "object")
7
- return "unknown_error";
8
- const errorCode = "code" in error ? error.code : undefined;
9
- const errorName = "name" in error ? error.name : undefined;
10
- const errorMessage = error instanceof Error ? error.message.toLowerCase() : "";
11
- // Abort errors
12
- if (errorCode === "ABORTED" ||
13
- errorName === "AbortError" ||
14
- errorMessage.includes("abort")) {
15
- return "abort_error";
16
- }
17
- // Size limit errors
18
- if (errorCode === "FILE_TOO_LARGE" ||
19
- errorCode === "LIMIT_FILE_SIZE" ||
20
- errorCode === "RequestEntityTooLarge" ||
21
- errorMessage.includes("too large") ||
22
- errorMessage.includes("size limit") ||
23
- errorMessage.includes("max size")) {
24
- return "size_limit_error";
25
- }
26
- // Validation errors
27
- if (errorCode === "INVALID_FILE" ||
28
- errorCode === "INVALID_METADATA" ||
29
- errorCode === "VALIDATION_ERROR" ||
30
- errorMessage.includes("validation") ||
31
- errorMessage.includes("invalid")) {
32
- return "validation_error";
33
- }
34
- // Network errors
35
- if (errorCode === "NetworkError" ||
36
- errorCode === "ECONNRESET" ||
37
- errorCode === "ENOTFOUND" ||
38
- errorCode === "ETIMEDOUT" ||
39
- errorMessage.includes("network") ||
40
- errorMessage.includes("timeout")) {
41
- return "network_error";
42
- }
43
- // Authentication errors
44
- if (errorCode === "UNAUTHORIZED" ||
45
- errorCode === "AuthenticationFailed" ||
46
- errorName === "AuthenticationError" ||
47
- errorMessage.includes("authentication") ||
48
- errorMessage.includes("unauthorized")) {
49
- return "authentication_error";
50
- }
51
- // Authorization errors
52
- if (errorCode === "FORBIDDEN" ||
53
- errorCode === "AccessDenied" ||
54
- errorName === "AuthorizationError" ||
55
- errorMessage.includes("forbidden") ||
56
- errorMessage.includes("permission")) {
57
- return "authorization_error";
58
- }
59
- // Storage errors
60
- if (errorCode === "FILE_WRITE_ERROR" ||
61
- errorCode === "STORAGE_ERROR" ||
62
- errorMessage.includes("storage") ||
63
- errorMessage.includes("write error")) {
64
- return "storage_error";
65
- }
66
- return "unknown_error";
67
- };
68
- /**
69
- * Track upload errors with metrics and structured logging
70
- */
71
- export const trackUploadError = (metrics, operation, error, context = {}) => Effect.gen(function* () {
72
- const errorCategory = classifyUploadError(error);
73
- // Record error metrics
74
- const errorMetric = metrics.uploadFailedTotal.pipe(Metric.tagged("operation", operation), Metric.tagged("error_category", errorCategory));
75
- yield* errorMetric(Effect.succeed(1));
76
- // Create detailed error context
77
- const errorDetails = {
78
- operation,
79
- error_category: errorCategory,
80
- error_type: typeof error,
81
- error_message: error instanceof Error ? error.message : String(error),
82
- error_code: error && typeof error === "object" && "code" in error
83
- ? String(error.code)
84
- : undefined,
85
- error_name: error && typeof error === "object" && "name" in error
86
- ? String(error.name)
87
- : undefined,
88
- ...context,
89
- };
90
- // Log structured error
91
- yield* Effect.logError(`Upload ${operation} failed`).pipe(Effect.annotateLogs(errorDetails));
92
- });
93
- /**
94
- * Create a custom error classifier for upload operations
95
- */
96
- export const createUploadErrorClassifier = (customErrorMapping) => {
97
- return (error) => {
98
- // Try custom mapping first
99
- if (customErrorMapping) {
100
- const customResult = customErrorMapping(error);
101
- if (customResult !== null)
102
- return customResult;
103
- }
104
- // Fall back to generic classification
105
- return classifyUploadError(error);
106
- };
107
- };
@@ -1,6 +0,0 @@
1
- export * from "./metrics.js";
2
- export * from "./tracing.js";
3
- export { makeUploadObservabilityLive, UploadObservabilityLive, getUploadMetrics, withUploadDuration, withChunkDuration, } from "./layers.js";
4
- export * from "./errors.js";
5
- export * from "./testing.js";
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upload/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
@@ -1,6 +0,0 @@
1
- // Upload observability exports
2
- export * from "./metrics.js";
3
- export * from "./tracing.js";
4
- export { makeUploadObservabilityLive, UploadObservabilityLive, getUploadMetrics, withUploadDuration, withChunkDuration, } from "./layers.js";
5
- export * from "./errors.js";
6
- export * from "./testing.js";
@@ -1,32 +0,0 @@
1
- import { Effect, Layer } from "effect";
2
- import { UploadObservability } from "../core/layers.js";
3
- /**
4
- * Create a live upload observability layer with full metrics
5
- */
6
- export declare const makeUploadObservabilityLive: (serviceName?: string) => Layer.Layer<UploadObservability>;
7
- /**
8
- * Default live upload observability layer
9
- */
10
- export declare const UploadObservabilityLive: Layer.Layer<UploadObservability, never, never>;
11
- /**
12
- * No-op upload observability layer (for testing or disabled observability)
13
- */
14
- export declare const UploadObservabilityDisabled: Layer.Layer<UploadObservability, never, never>;
15
- /**
16
- * Helper to get upload metrics from context
17
- */
18
- export declare const getUploadMetrics: Effect.Effect<{
19
- uploadCreated: Effect.Effect<void>;
20
- uploadCompleted: Effect.Effect<void>;
21
- uploadFailed: Effect.Effect<void>;
22
- chunkUploaded: Effect.Effect<void>;
23
- }, never, UploadObservability>;
24
- /**
25
- * Helper to track upload duration
26
- */
27
- export declare const withUploadDuration: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R | UploadObservability>;
28
- /**
29
- * Helper to track chunk upload duration
30
- */
31
- export declare const withChunkDuration: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
32
- //# sourceMappingURL=layers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/upload/layers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAEL,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAO3B;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,oBAAwC,KACvC,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAqBjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,gDAAgC,CAAC;AAErE;;GAEG;AACH,eAAO,MAAM,2BAA2B,gDAAsC,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;8BAG3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACxC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,mBAAmB,CAS7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACvC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CASvB,CAAC"}
@@ -1,63 +0,0 @@
1
- import { Effect, Layer, Metric } from "effect";
2
- import { makeUploadObservabilityLayer, UploadObservability, } from "../core/layers.js";
3
- import { createUploadServerMetrics } from "./metrics.js";
4
- // ============================================================================
5
- // Upload Observability Layer Implementation
6
- // ============================================================================
7
- /**
8
- * Create a live upload observability layer with full metrics
9
- */
10
- export const makeUploadObservabilityLive = (serviceName = "uploadista-upload-server") => {
11
- const metrics = createUploadServerMetrics();
12
- return Layer.succeed(UploadObservability, {
13
- serviceName,
14
- enabled: true,
15
- metrics: {
16
- uploadCreated: Effect.succeed(metrics.uploadCreatedTotal).pipe(Effect.flatMap((metric) => Metric.increment(metric))),
17
- uploadCompleted: Effect.succeed(metrics.uploadCompletedTotal).pipe(Effect.flatMap((metric) => Metric.increment(metric))),
18
- uploadFailed: Effect.succeed(metrics.uploadFailedTotal).pipe(Effect.flatMap((metric) => Metric.increment(metric))),
19
- chunkUploaded: Effect.succeed(metrics.chunkUploadedTotal).pipe(Effect.flatMap((metric) => Metric.increment(metric))),
20
- },
21
- });
22
- };
23
- /**
24
- * Default live upload observability layer
25
- */
26
- export const UploadObservabilityLive = makeUploadObservabilityLive();
27
- /**
28
- * No-op upload observability layer (for testing or disabled observability)
29
- */
30
- export const UploadObservabilityDisabled = makeUploadObservabilityLayer(false);
31
- /**
32
- * Helper to get upload metrics from context
33
- */
34
- export const getUploadMetrics = Effect.gen(function* () {
35
- const obs = yield* UploadObservability;
36
- return obs.metrics;
37
- });
38
- /**
39
- * Helper to track upload duration
40
- */
41
- export const withUploadDuration = (effect) => {
42
- const metrics = createUploadServerMetrics();
43
- return Effect.gen(function* () {
44
- const startTime = Date.now();
45
- const result = yield* effect;
46
- const duration = (Date.now() - startTime) / 1000; // Convert to seconds
47
- yield* Metric.update(metrics.uploadDurationHistogram, duration);
48
- return result;
49
- }).pipe(Effect.withSpan("upload-operation"));
50
- };
51
- /**
52
- * Helper to track chunk upload duration
53
- */
54
- export const withChunkDuration = (effect) => {
55
- const metrics = createUploadServerMetrics();
56
- return Effect.gen(function* () {
57
- const startTime = Date.now();
58
- const result = yield* effect;
59
- const duration = (Date.now() - startTime) / 1000; // Convert to seconds
60
- yield* Metric.update(metrics.chunkUploadDurationHistogram, duration);
61
- return result;
62
- }).pipe(Effect.withSpan("chunk-upload"));
63
- };
@@ -1,46 +0,0 @@
1
- import { Metric } from "effect";
2
- /**
3
- * Upload server metrics for tracking upload operations
4
- */
5
- export declare const createUploadServerMetrics: () => {
6
- uploadCreatedTotal: Metric.Metric.Counter<number>;
7
- uploadCompletedTotal: Metric.Metric.Counter<number>;
8
- uploadFailedTotal: Metric.Metric.Counter<number>;
9
- chunkUploadedTotal: Metric.Metric.Counter<number>;
10
- uploadFromUrlTotal: Metric.Metric.Counter<number>;
11
- uploadFromUrlSuccessTotal: Metric.Metric.Counter<number>;
12
- uploadFromUrlFailedTotal: Metric.Metric.Counter<number>;
13
- uploadDurationHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
14
- chunkUploadDurationHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
15
- uploadFileSizeHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
16
- chunkSizeHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
17
- activeUploadsGauge: Metric.Metric.Gauge<number>;
18
- uploadThroughputGauge: Metric.Metric.Gauge<number>;
19
- uploadLatencySummary: Metric.Metric.Summary<number>;
20
- chunkLatencySummary: Metric.Metric.Summary<number>;
21
- };
22
- /**
23
- * Type for upload server metrics
24
- */
25
- export type UploadServerMetrics = ReturnType<typeof createUploadServerMetrics>;
26
- /**
27
- * Default upload server metrics instance
28
- */
29
- export declare const uploadServerMetrics: {
30
- uploadCreatedTotal: Metric.Metric.Counter<number>;
31
- uploadCompletedTotal: Metric.Metric.Counter<number>;
32
- uploadFailedTotal: Metric.Metric.Counter<number>;
33
- chunkUploadedTotal: Metric.Metric.Counter<number>;
34
- uploadFromUrlTotal: Metric.Metric.Counter<number>;
35
- uploadFromUrlSuccessTotal: Metric.Metric.Counter<number>;
36
- uploadFromUrlFailedTotal: Metric.Metric.Counter<number>;
37
- uploadDurationHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
38
- chunkUploadDurationHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
39
- uploadFileSizeHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
40
- chunkSizeHistogram: Metric.Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
41
- activeUploadsGauge: Metric.Metric.Gauge<number>;
42
- uploadThroughputGauge: Metric.Metric.Gauge<number>;
43
- uploadLatencySummary: Metric.Metric.Summary<number>;
44
- chunkLatencySummary: Metric.Metric.Summary<number>;
45
- };
46
- //# sourceMappingURL=metrics.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/upload/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAoB,MAAM,QAAQ,CAAC;AAMlD;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;CAkGpC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;CAA8B,CAAC"}
@@ -1,80 +0,0 @@
1
- import { Metric, MetricBoundaries } from "effect";
2
- // ============================================================================
3
- // Upload Server Metrics
4
- // ============================================================================
5
- /**
6
- * Upload server metrics for tracking upload operations
7
- */
8
- export const createUploadServerMetrics = () => ({
9
- // Counter metrics
10
- uploadCreatedTotal: Metric.counter("upload_created_total", {
11
- description: "Total number of uploads created",
12
- }),
13
- uploadCompletedTotal: Metric.counter("upload_completed_total", {
14
- description: "Total number of uploads completed successfully",
15
- }),
16
- uploadFailedTotal: Metric.counter("upload_failed_total", {
17
- description: "Total number of uploads that failed",
18
- }),
19
- chunkUploadedTotal: Metric.counter("chunk_uploaded_total", {
20
- description: "Total number of chunks uploaded",
21
- }),
22
- uploadFromUrlTotal: Metric.counter("upload_from_url_total", {
23
- description: "Total number of URL-based uploads",
24
- }),
25
- uploadFromUrlSuccessTotal: Metric.counter("upload_from_url_success_total", {
26
- description: "Total number of successful URL-based uploads",
27
- }),
28
- uploadFromUrlFailedTotal: Metric.counter("upload_from_url_failed_total", {
29
- description: "Total number of failed URL-based uploads",
30
- }),
31
- // Histogram metrics
32
- uploadDurationHistogram: Metric.histogram("upload_duration_seconds", MetricBoundaries.exponential({
33
- start: 0.01, // 10ms
34
- factor: 2,
35
- count: 20, // Up to ~10 seconds
36
- }), "Duration of complete upload operations in seconds"),
37
- chunkUploadDurationHistogram: Metric.histogram("chunk_upload_duration_seconds", MetricBoundaries.exponential({
38
- start: 0.001, // 1ms
39
- factor: 2,
40
- count: 15, // Up to ~32 seconds
41
- }), "Duration of individual chunk uploads in seconds"),
42
- uploadFileSizeHistogram: Metric.histogram("upload_file_size_bytes", MetricBoundaries.exponential({
43
- start: 1024, // 1KB
44
- factor: 2,
45
- count: 25, // Up to ~33GB
46
- }), "Size of uploaded files in bytes"),
47
- chunkSizeHistogram: Metric.histogram("chunk_size_bytes", MetricBoundaries.linear({
48
- start: 262_144, // 256KB
49
- width: 262_144, // 256KB increments
50
- count: 20, // Up to ~5MB
51
- }), "Size of uploaded chunks in bytes"),
52
- // Gauge metrics
53
- activeUploadsGauge: Metric.gauge("active_uploads", {
54
- description: "Number of currently active uploads",
55
- }),
56
- uploadThroughputGauge: Metric.gauge("upload_throughput_bytes_per_second", {
57
- description: "Current upload throughput in bytes per second",
58
- }),
59
- // Summary metrics for latency percentiles
60
- uploadLatencySummary: Metric.summary({
61
- name: "upload_latency_seconds",
62
- maxAge: "10 minutes",
63
- maxSize: 1000,
64
- error: 0.01,
65
- quantiles: [0.5, 0.9, 0.95, 0.99],
66
- description: "Upload operation latency percentiles",
67
- }),
68
- chunkLatencySummary: Metric.summary({
69
- name: "chunk_latency_seconds",
70
- maxAge: "10 minutes",
71
- maxSize: 1000,
72
- error: 0.01,
73
- quantiles: [0.5, 0.9, 0.95, 0.99],
74
- description: "Chunk upload latency percentiles",
75
- }),
76
- });
77
- /**
78
- * Default upload server metrics instance
79
- */
80
- export const uploadServerMetrics = createUploadServerMetrics();
@@ -1,32 +0,0 @@
1
- import { Layer } from "effect";
2
- import { UploadObservability } from "../core/layers.js";
3
- /**
4
- * Create a test upload observability layer that doesn't actually emit metrics
5
- * but validates that the observability system is wired correctly
6
- */
7
- export declare const UploadObservabilityTest: Layer.Layer<UploadObservability, never, never>;
8
- /**
9
- * Get metrics for validation (useful for testing metric definitions)
10
- */
11
- export declare const getTestMetrics: () => {
12
- uploadCreatedTotal: import("effect/Metric").Metric.Counter<number>;
13
- uploadCompletedTotal: import("effect/Metric").Metric.Counter<number>;
14
- uploadFailedTotal: import("effect/Metric").Metric.Counter<number>;
15
- chunkUploadedTotal: import("effect/Metric").Metric.Counter<number>;
16
- uploadFromUrlTotal: import("effect/Metric").Metric.Counter<number>;
17
- uploadFromUrlSuccessTotal: import("effect/Metric").Metric.Counter<number>;
18
- uploadFromUrlFailedTotal: import("effect/Metric").Metric.Counter<number>;
19
- uploadDurationHistogram: import("effect/Metric").Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
20
- chunkUploadDurationHistogram: import("effect/Metric").Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
21
- uploadFileSizeHistogram: import("effect/Metric").Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
22
- chunkSizeHistogram: import("effect/Metric").Metric<import("effect/MetricKeyType").MetricKeyType.Histogram, number, import("effect/MetricState").MetricState.Histogram>;
23
- activeUploadsGauge: import("effect/Metric").Metric.Gauge<number>;
24
- uploadThroughputGauge: import("effect/Metric").Metric.Gauge<number>;
25
- uploadLatencySummary: import("effect/Metric").Metric.Summary<number>;
26
- chunkLatencySummary: import("effect/Metric").Metric.Summary<number>;
27
- };
28
- /**
29
- * Validate that all required metrics exist
30
- */
31
- export declare const validateMetricsExist: () => boolean;
32
- //# sourceMappingURL=testing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/upload/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAOxD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,gDASlC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;CAAoC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,oBAAoB,eA4BhC,CAAC"}
@@ -1,52 +0,0 @@
1
- import { Layer } from "effect";
2
- import { UploadObservability } from "../core/layers.js";
3
- import { createUploadServerMetrics } from "./metrics.js";
4
- // ============================================================================
5
- // Upload Observability Testing Utilities
6
- // ============================================================================
7
- /**
8
- * Create a test upload observability layer that doesn't actually emit metrics
9
- * but validates that the observability system is wired correctly
10
- */
11
- export const UploadObservabilityTest = Layer.succeed(UploadObservability, {
12
- serviceName: "uploadista-upload-server-test",
13
- enabled: true,
14
- metrics: {
15
- uploadCreated: () => Promise.resolve(),
16
- uploadCompleted: () => Promise.resolve(),
17
- uploadFailed: () => Promise.resolve(),
18
- chunkUploaded: () => Promise.resolve(),
19
- },
20
- });
21
- /**
22
- * Get metrics for validation (useful for testing metric definitions)
23
- */
24
- export const getTestMetrics = () => createUploadServerMetrics();
25
- /**
26
- * Validate that all required metrics exist
27
- */
28
- export const validateMetricsExist = () => {
29
- const metrics = getTestMetrics();
30
- const requiredMetrics = [
31
- "uploadCreatedTotal",
32
- "uploadCompletedTotal",
33
- "uploadFailedTotal",
34
- "chunkUploadedTotal",
35
- "uploadFromUrlTotal",
36
- "uploadFromUrlSuccessTotal",
37
- "uploadFromUrlFailedTotal",
38
- "uploadDurationHistogram",
39
- "chunkUploadDurationHistogram",
40
- "uploadFileSizeHistogram",
41
- "chunkSizeHistogram",
42
- "activeUploadsGauge",
43
- "uploadThroughputGauge",
44
- "uploadLatencySummary",
45
- "chunkLatencySummary",
46
- ];
47
- const missingMetrics = requiredMetrics.filter((name) => !(name in metrics));
48
- if (missingMetrics.length > 0) {
49
- throw new Error(`Missing required metrics: ${missingMetrics.join(", ")}`);
50
- }
51
- return true;
52
- };
@@ -1,25 +0,0 @@
1
- import { Effect } from "effect";
2
- /**
3
- * Wrap an Effect with an upload operation span
4
- */
5
- export declare const withUploadSpan: <A, E, R>(operation: string, attributes?: Record<string, unknown>) => (effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
6
- /**
7
- * Add upload context to the current span
8
- */
9
- export declare const withUploadContext: (context: {
10
- uploadId?: string;
11
- fileName?: string;
12
- fileSize?: number;
13
- storageId?: string;
14
- mimeType?: string;
15
- }) => Effect.Effect<void, never, never>;
16
- /**
17
- * Add chunk context to the current span
18
- */
19
- export declare const withChunkContext: (context: {
20
- uploadId: string;
21
- chunkSize: number;
22
- offset: number;
23
- totalSize?: number;
24
- }) => Effect.Effect<void, never, never>;
25
- //# sourceMappingURL=tracing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/upload/tracing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAMhC;;GAEG;AACH,eAAO,MAAM,cAAc,GACxB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,WAAW,MAAM,EAAE,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAChE,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAQpD,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,sCAOG,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,sCAUG,CAAC"}