@sayoriqwq/effect-harness 0.0.1
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.
- package/HARNESS.md +34 -0
- package/README.md +113 -0
- package/dist/bin/effect-harness.d.ts +2 -0
- package/dist/bin/effect-harness.js +39 -0
- package/dist/bin/effect-harness.js.map +1 -0
- package/dist/src/cli/Main.d.ts +6 -0
- package/dist/src/cli/Main.js +141 -0
- package/dist/src/cli/Main.js.map +1 -0
- package/dist/src/harness/CraftSkills.d.ts +14 -0
- package/dist/src/harness/CraftSkills.js +164 -0
- package/dist/src/harness/CraftSkills.js.map +1 -0
- package/dist/src/harness/Errors.d.ts +24 -0
- package/dist/src/harness/Errors.js +26 -0
- package/dist/src/harness/Errors.js.map +1 -0
- package/dist/src/harness/GuardrailRules.d.ts +6 -0
- package/dist/src/harness/GuardrailRules.js +303 -0
- package/dist/src/harness/GuardrailRules.js.map +1 -0
- package/dist/src/harness/Guardrails.d.ts +10 -0
- package/dist/src/harness/Guardrails.js +69 -0
- package/dist/src/harness/Guardrails.js.map +1 -0
- package/dist/src/harness/Init.d.ts +9 -0
- package/dist/src/harness/Init.js +234 -0
- package/dist/src/harness/Init.js.map +1 -0
- package/dist/src/harness/Model.d.ts +44 -0
- package/dist/src/harness/Model.js +169 -0
- package/dist/src/harness/Model.js.map +1 -0
- package/dist/src/harness/ModuleSources.d.ts +5 -0
- package/dist/src/harness/ModuleSources.js +47 -0
- package/dist/src/harness/ModuleSources.js.map +1 -0
- package/dist/src/harness/PnpmWorkspace.d.ts +2 -0
- package/dist/src/harness/PnpmWorkspace.js +23 -0
- package/dist/src/harness/PnpmWorkspace.js.map +1 -0
- package/dist/src/harness/Publish.d.ts +53 -0
- package/dist/src/harness/Publish.js +282 -0
- package/dist/src/harness/Publish.js.map +1 -0
- package/dist/src/harness/SelfVerify.d.ts +4 -0
- package/dist/src/harness/SelfVerify.js +56 -0
- package/dist/src/harness/SelfVerify.js.map +1 -0
- package/dist/src/harness/SourcePin.d.ts +12 -0
- package/dist/src/harness/SourcePin.js +320 -0
- package/dist/src/harness/SourcePin.js.map +1 -0
- package/dist/src/harness/Status.d.ts +12 -0
- package/dist/src/harness/Status.js +88 -0
- package/dist/src/harness/Status.js.map +1 -0
- package/dist/src/harness/TargetVerify.d.ts +8 -0
- package/dist/src/harness/TargetVerify.js +432 -0
- package/dist/src/harness/TargetVerify.js.map +1 -0
- package/dist/src/harness/TestContract.d.ts +6 -0
- package/dist/src/harness/TestContract.js +45 -0
- package/dist/src/harness/TestContract.js.map +1 -0
- package/dist/src/platform/Json.d.ts +8 -0
- package/dist/src/platform/Json.js +35 -0
- package/dist/src/platform/Json.js.map +1 -0
- package/dist/src/platform/ManagedFiles.d.ts +8 -0
- package/dist/src/platform/ManagedFiles.js +59 -0
- package/dist/src/platform/ManagedFiles.js.map +1 -0
- package/dist/src/platform/Process.d.ts +8 -0
- package/dist/src/platform/Process.js +80 -0
- package/dist/src/platform/Process.js.map +1 -0
- package/guide/default-capabilities.md +38 -0
- package/guide/index.md +49 -0
- package/guide/setup.md +64 -0
- package/harness/default-capabilities.md +32 -0
- package/harness/exposure.md +46 -0
- package/harness/feedback/index.md +60 -0
- package/harness/index.md +22 -0
- package/harness/official-inventory.md +85 -0
- package/harness/runtime/codex/AGENTS.fragment.md +28 -0
- package/harness/runtime/codex/agents/effect-worker.md +26 -0
- package/harness/runtime/codex/skills/effect-code/SKILL.md +72 -0
- package/harness/runtime/codex/skills/effect-code/agents/openai.yaml +4 -0
- package/harness/runtime/codex/skills/effect-feedback/SKILL.md +66 -0
- package/harness/runtime/codex/skills/effect-feedback/agents/openai.yaml +4 -0
- package/harness/source.md +52 -0
- package/harness/target-agent-contract.md +205 -0
- package/package.json +68 -0
- package/repos/craft-skills.manifest.json +34 -0
- package/repos/effect/.agents/skills/grill-me/SKILL.md +43 -0
- package/repos/effect/.agents/skills/jsdocs/SKILL.md +203 -0
- package/repos/effect/.agents/skills/scratchpad/SKILL.md +44 -0
- package/repos/effect/.agents/skills/scratchpad/agents/openai.yaml +7 -0
- package/repos/effect/.agents/skills/scratchpad/scripts/extract-example.mjs +260 -0
- package/repos/effect/.changeset/add-bigdecimal-sumall-multiplyall.md +5 -0
- package/repos/effect/.changeset/add-chunk-schema.md +5 -0
- package/repos/effect/.changeset/add-command-hidden.md +19 -0
- package/repos/effect/.changeset/add-config-nested.md +5 -0
- package/repos/effect/.changeset/add-flag-hidden.md +15 -0
- package/repos/effect/.changeset/add-from-string-schemas.md +5 -0
- package/repos/effect/.changeset/add-headers-remove-many.md +5 -0
- package/repos/effect/.changeset/add-indexeddb-kvs-layer.md +5 -0
- package/repos/effect/.changeset/add-make-msgpack.md +5 -0
- package/repos/effect/.changeset/add-make-option.md +5 -0
- package/repos/effect/.changeset/add-missing-tx-modules.md +11 -0
- package/repos/effect/.changeset/add-newtype-module.md +5 -0
- package/repos/effect/.changeset/add-scalar-show-operation-id.md +5 -0
- package/repos/effect/.changeset/add-schedule-tap.md +5 -0
- package/repos/effect/.changeset/add-schema-annotate-encoded.md +5 -0
- package/repos/effect/.changeset/add-schema-array-ensure.md +5 -0
- package/repos/effect/.changeset/add-schema-bigdecimal.md +5 -0
- package/repos/effect/.changeset/add-schema-datetime.md +5 -0
- package/repos/effect/.changeset/add-schema-option-from-optional-nullor.md +5 -0
- package/repos/effect/.changeset/add-schema-option-from-undefined-nullish.md +5 -0
- package/repos/effect/.changeset/add-schema-string-encoding.md +5 -0
- package/repos/effect/.changeset/add-sql-pglite.md +5 -0
- package/repos/effect/.changeset/add-standard-jsdoc-rule.md +5 -0
- package/repos/effect/.changeset/add-stream-broadcastn.md +5 -0
- package/repos/effect/.changeset/add-unstable-encoding-export.md +5 -0
- package/repos/effect/.changeset/afraid-cobras-like.md +5 -0
- package/repos/effect/.changeset/ai-openai-config-field-leak.md +6 -0
- package/repos/effect/.changeset/ai-openai-file-nullable-fields.md +5 -0
- package/repos/effect/.changeset/anthropic-4-6-structured-output.md +5 -0
- package/repos/effect/.changeset/asyncresult-exhaustive.md +5 -0
- package/repos/effect/.changeset/atom-stream-error-type.md +5 -0
- package/repos/effect/.changeset/beige-paths-sort.md +5 -0
- package/repos/effect/.changeset/better-apples-nail.md +5 -0
- package/repos/effect/.changeset/better-rocks-arrive.md +5 -0
- package/repos/effect/.changeset/big-pans-look.md +5 -0
- package/repos/effect/.changeset/blue-dingos-greet.md +5 -0
- package/repos/effect/.changeset/blue-ligers-cheat.md +5 -0
- package/repos/effect/.changeset/blue-onions-smile.md +5 -0
- package/repos/effect/.changeset/blue-ravens-type.md +5 -0
- package/repos/effect/.changeset/blue-trams-kiss.md +7 -0
- package/repos/effect/.changeset/bold-chairs-yawn.md +5 -0
- package/repos/effect/.changeset/bold-planets-shout.md +30 -0
- package/repos/effect/.changeset/breezy-meals-see.md +5 -0
- package/repos/effect/.changeset/bright-bugs-bow.md +5 -0
- package/repos/effect/.changeset/bright-canyons-clean.md +5 -0
- package/repos/effect/.changeset/bright-dogs-fail.md +5 -0
- package/repos/effect/.changeset/bright-flags-stand.md +5 -0
- package/repos/effect/.changeset/bright-laws-teach.md +5 -0
- package/repos/effect/.changeset/bright-lemons-dance.md +5 -0
- package/repos/effect/.changeset/bright-planes-smash.md +5 -0
- package/repos/effect/.changeset/bright-rats-attend.md +5 -0
- package/repos/effect/.changeset/bright-toes-rush.md +5 -0
- package/repos/effect/.changeset/bumpy-boxes-teach.md +5 -0
- package/repos/effect/.changeset/busy-lions-sneeze.md +5 -0
- package/repos/effect/.changeset/busy-maps-attend.md +7 -0
- package/repos/effect/.changeset/calm-buckets-own.md +5 -0
- package/repos/effect/.changeset/calm-carrots-march.md +7 -0
- package/repos/effect/.changeset/calm-cars-rest.md +5 -0
- package/repos/effect/.changeset/calm-panthers-nail.md +5 -0
- package/repos/effect/.changeset/calm-seas-smile.md +5 -0
- package/repos/effect/.changeset/calm-squids-hug.md +5 -0
- package/repos/effect/.changeset/chatty-poets-type.md +5 -0
- package/repos/effect/.changeset/chilled-mice-wash.md +5 -0
- package/repos/effect/.changeset/chilly-pumas-rule.md +5 -0
- package/repos/effect/.changeset/chubby-buckets-feel.md +5 -0
- package/repos/effect/.changeset/chubby-parents-flow.md +5 -0
- package/repos/effect/.changeset/chubby-planets-fall.md +5 -0
- package/repos/effect/.changeset/clean-balloons-tan.md +5 -0
- package/repos/effect/.changeset/clean-bulldogs-care.md +5 -0
- package/repos/effect/.changeset/clean-dryers-sneeze.md +5 -0
- package/repos/effect/.changeset/clean-geese-work.md +5 -0
- package/repos/effect/.changeset/clean-goats-wave.md +5 -0
- package/repos/effect/.changeset/clean-needles-shake.md +23 -0
- package/repos/effect/.changeset/clean-tires-guess.md +5 -0
- package/repos/effect/.changeset/clear-spies-boil.md +5 -0
- package/repos/effect/.changeset/cli-help-choices.md +5 -0
- package/repos/effect/.changeset/cold-knives-lie.md +35 -0
- package/repos/effect/.changeset/cold-rooms-show.md +5 -0
- package/repos/effect/.changeset/cold-sloths-wave.md +5 -0
- package/repos/effect/.changeset/compact-json-schema-enum.md +25 -0
- package/repos/effect/.changeset/config-withdefault-eager.md +7 -0
- package/repos/effect/.changeset/config.json +24 -0
- package/repos/effect/.changeset/consolidate-encoding.md +5 -0
- package/repos/effect/.changeset/consolidate-sql-error.md +16 -0
- package/repos/effect/.changeset/crisp-seas-warn.md +5 -0
- package/repos/effect/.changeset/cuddly-rooms-bet.md +5 -0
- package/repos/effect/.changeset/curly-poems-talk.md +5 -0
- package/repos/effect/.changeset/curly-spies-relax.md +5 -0
- package/repos/effect/.changeset/curvy-apples-float.md +5 -0
- package/repos/effect/.changeset/custom-http-security-openapi-generator.md +5 -0
- package/repos/effect/.changeset/cute-heads-thank.md +5 -0
- package/repos/effect/.changeset/cyan-loops-grow.md +5 -0
- package/repos/effect/.changeset/cyan-radios-switch.md +5 -0
- package/repos/effect/.changeset/deep-rivers-spend.md +5 -0
- package/repos/effect/.changeset/dirty-lamps-trade.md +5 -0
- package/repos/effect/.changeset/dirty-laws-wear.md +5 -0
- package/repos/effect/.changeset/duration-temporal-object-input.md +7 -0
- package/repos/effect/.changeset/eager-coats-cheat.md +5 -0
- package/repos/effect/.changeset/early-birds-dream.md +5 -0
- package/repos/effect/.changeset/early-donuts-argue.md +5 -0
- package/repos/effect/.changeset/early-peaches-check.md +6 -0
- package/repos/effect/.changeset/eff-691-default-logger-ordering.md +5 -0
- package/repos/effect/.changeset/eff-693-rpcgroup-handler-deps.md +5 -0
- package/repos/effect/.changeset/eff-694-cli-completions-module.md +5 -0
- package/repos/effect/.changeset/eff-695-layer-mock-dual-api.md +5 -0
- package/repos/effect/.changeset/eff-697-rpcserialization-json-array-decode.md +5 -0
- package/repos/effect/.changeset/eff-698-rpcserialization-unreachable-branch.md +5 -0
- package/repos/effect/.changeset/eff-700-httpapi-middleware-errors.md +12 -0
- package/repos/effect/.changeset/eff-701-httpapierror-respondable.md +5 -0
- package/repos/effect/.changeset/eff-704-stream-merge-predicate.md +5 -0
- package/repos/effect/.changeset/eff-705-layer-tap-apis.md +5 -0
- package/repos/effect/.changeset/eff-706-servicemap-mutate.md +6 -0
- package/repos/effect/.changeset/eff-716-response-id-tracker-map.md +5 -0
- package/repos/effect/.changeset/eff-717-openai-socket-cancel.md +5 -0
- package/repos/effect/.changeset/eff-718-embedding-model-surface.md +13 -0
- package/repos/effect/.changeset/eff-725-fix-catch-jsdoc.md +5 -0
- package/repos/effect/.changeset/eff-726-model-dimensions.md +7 -0
- package/repos/effect/.changeset/eff-727-cli-help-alignment.md +5 -0
- package/repos/effect/.changeset/eff-730-language-model-incremental-fallback.md +5 -0
- package/repos/effect/.changeset/eff-736-cached-with-ttl.md +5 -0
- package/repos/effect/.changeset/eff-738-cron-prev.md +5 -0
- package/repos/effect/.changeset/eff-739-openai-function-call-done.md +5 -0
- package/repos/effect/.changeset/eff-740-missing-summary-parts.md +5 -0
- package/repos/effect/.changeset/eff-742-http-client-request-web.md +5 -0
- package/repos/effect/.changeset/eff-744-sqlite-migrator-lock.md +5 -0
- package/repos/effect/.changeset/eff-746-fixed-iteration-catchup.md +5 -0
- package/repos/effect/.changeset/eff-747-unify-effect.md +5 -0
- package/repos/effect/.changeset/eff-754-url-builder-any.md +6 -0
- package/repos/effect/.changeset/eff-755-references-core.md +5 -0
- package/repos/effect/.changeset/eff-769-select-text-highlight.md +5 -0
- package/repos/effect/.changeset/eff-774-mutable-list-append-all-empty-array.md +5 -0
- package/repos/effect/.changeset/eff-777-schema-make-effect.md +5 -0
- package/repos/effect/.changeset/eff-778-http-middleware-path-logger.md +5 -0
- package/repos/effect/.changeset/eff-779-keyvaluestore-layer-sql.md +5 -0
- package/repos/effect/.changeset/eff-780-layer-unify.md +5 -0
- package/repos/effect/.changeset/eff-781-fix-stream-toqueue-types.md +5 -0
- package/repos/effect/.changeset/eff-782-httpapi-status-literals.md +5 -0
- package/repos/effect/.changeset/eff-783-atom-http-api-errors.md +5 -0
- package/repos/effect/.changeset/eff-819-cluster-workflow-shard-groups.md +5 -0
- package/repos/effect/.changeset/eight-turkeys-own.md +7 -0
- package/repos/effect/.changeset/eighty-lies-deny.md +5 -0
- package/repos/effect/.changeset/eighty-poets-draw.md +9 -0
- package/repos/effect/.changeset/eighty-swans-scream.md +5 -0
- package/repos/effect/.changeset/eighty-teeth-sniff.md +5 -0
- package/repos/effect/.changeset/eleven-apes-share.md +5 -0
- package/repos/effect/.changeset/eleven-numbers-bake.md +5 -0
- package/repos/effect/.changeset/empty-gifts-beg.md +5 -0
- package/repos/effect/.changeset/empty-http-rpc-client.md +5 -0
- package/repos/effect/.changeset/eventlog-unencrypted.md +5 -0
- package/repos/effect/.changeset/expand-schema-filter-output.md +24 -0
- package/repos/effect/.changeset/export-schema-encode-keys-interface.md +7 -0
- package/repos/effect/.changeset/extract-semaphore-latch.md +10 -0
- package/repos/effect/.changeset/fair-bees-relax.md +5 -0
- package/repos/effect/.changeset/fair-buttons-share.md +7 -0
- package/repos/effect/.changeset/fair-cooks-stop.md +5 -0
- package/repos/effect/.changeset/fair-cups-train.md +5 -0
- package/repos/effect/.changeset/fair-dryers-speak.md +5 -0
- package/repos/effect/.changeset/fair-forks-shake.md +5 -0
- package/repos/effect/.changeset/fair-pandas-prove.md +5 -0
- package/repos/effect/.changeset/fair-pants-float.md +5 -0
- package/repos/effect/.changeset/fair-poems-visit.md +5 -0
- package/repos/effect/.changeset/famous-wolves-lead.md +5 -0
- package/repos/effect/.changeset/fancy-glasses-grow.md +5 -0
- package/repos/effect/.changeset/fast-times-camp.md +5 -0
- package/repos/effect/.changeset/few-birds-matter.md +5 -0
- package/repos/effect/.changeset/few-cougars-dig.md +5 -0
- package/repos/effect/.changeset/few-foxes-grin.md +5 -0
- package/repos/effect/.changeset/few-mirrors-pull.md +14 -0
- package/repos/effect/.changeset/few-socks-poke.md +5 -0
- package/repos/effect/.changeset/fiber-runtime-start-metrics.md +5 -0
- package/repos/effect/.changeset/fiery-jokes-care.md +5 -0
- package/repos/effect/.changeset/fiery-mammals-call.md +5 -0
- package/repos/effect/.changeset/fine-walls-decide.md +5 -0
- package/repos/effect/.changeset/first-success-of.md +5 -0
- package/repos/effect/.changeset/five-parents-relax.md +5 -0
- package/repos/effect/.changeset/five-worms-rhyme.md +5 -0
- package/repos/effect/.changeset/fix-1332.md +5 -0
- package/repos/effect/.changeset/fix-1917.md +11 -0
- package/repos/effect/.changeset/fix-1927.md +5 -0
- package/repos/effect/.changeset/fix-1940.md +7 -0
- package/repos/effect/.changeset/fix-1947.md +7 -0
- package/repos/effect/.changeset/fix-2002.md +5 -0
- package/repos/effect/.changeset/fix-2012.md +5 -0
- package/repos/effect/.changeset/fix-2015.md +5 -0
- package/repos/effect/.changeset/fix-2260.md +5 -0
- package/repos/effect/.changeset/fix-2268.md +5 -0
- package/repos/effect/.changeset/fix-2271.md +5 -0
- package/repos/effect/.changeset/fix-2384.md +7 -0
- package/repos/effect/.changeset/fix-ai-empty-params-structured-output.md +5 -0
- package/repos/effect/.changeset/fix-ai-text-toolkit-typing.md +5 -0
- package/repos/effect/.changeset/fix-catch-orelse-error-erasure.md +5 -0
- package/repos/effect/.changeset/fix-class-constructor-defaults.md +5 -0
- package/repos/effect/.changeset/fix-cli-mixed-global-flag-context.md +7 -0
- package/repos/effect/.changeset/fix-config-withDefault.md +5 -0
- package/repos/effect/.changeset/fix-config-withdefault-filter.md +7 -0
- package/repos/effect/.changeset/fix-datetime-gmt.md +5 -0
- package/repos/effect/.changeset/fix-devtools-flush-on-teardown.md +10 -0
- package/repos/effect/.changeset/fix-duration-symmetric-rounding.md +5 -0
- package/repos/effect/.changeset/fix-entity-manager-defect-replay.md +5 -0
- package/repos/effect/.changeset/fix-entity-proxy-rpc-handler-context.md +5 -0
- package/repos/effect/.changeset/fix-entity-proxy-server-path-params.md +5 -0
- package/repos/effect/.changeset/fix-from-readable-stream-cancel-defect.md +5 -0
- package/repos/effect/.changeset/fix-graph-undirected-traversal.md +5 -0
- package/repos/effect/.changeset/fix-has-interrupts-only-empty.md +5 -0
- package/repos/effect/.changeset/fix-hashmap-bit31-ordering.md +5 -0
- package/repos/effect/.changeset/fix-headers-proto-enumerability.md +5 -0
- package/repos/effect/.changeset/fix-http-incoming-message-parse-options.md +5 -0
- package/repos/effect/.changeset/fix-httpapi-endpoint-error-inference.md +5 -0
- package/repos/effect/.changeset/fix-httpapi-schema-types.md +5 -0
- package/repos/effect/.changeset/fix-httpapi-security-middleware-cache.md +5 -0
- package/repos/effect/.changeset/fix-is-json-dag.md +7 -0
- package/repos/effect/.changeset/fix-json-schema-anyof-oneof-siblings.md +5 -0
- package/repos/effect/.changeset/fix-json-schema-import-json.md +5 -0
- package/repos/effect/.changeset/fix-keepalive-blocked-timers.md +5 -0
- package/repos/effect/.changeset/fix-mcp-param-name-resolution.md +5 -0
- package/repos/effect/.changeset/fix-mermaid-escape-special-chars.md +5 -0
- package/repos/effect/.changeset/fix-mutable-list-filter-length.md +5 -0
- package/repos/effect/.changeset/fix-object-keyword-json-schema.md +5 -0
- package/repos/effect/.changeset/fix-openai-mcp-tool-names.md +5 -0
- package/repos/effect/.changeset/fix-openapi-generator-form-urlencoded.md +5 -0
- package/repos/effect/.changeset/fix-openapi-generator-swagger2openapi.md +5 -0
- package/repos/effect/.changeset/fix-openapi-preserve-multiple-response-content-types.md +5 -0
- package/repos/effect/.changeset/fix-openrouter-sparse-array.md +5 -0
- package/repos/effect/.changeset/fix-otel-logger-clock-skew.md +7 -0
- package/repos/effect/.changeset/fix-otel-logger-severity-number.md +20 -0
- package/repos/effect/.changeset/fix-queue-collect-duplication.md +5 -0
- package/repos/effect/.changeset/fix-random-string-seeds.md +5 -0
- package/repos/effect/.changeset/fix-ratelimiter-tokenbucket-redis-ttl.md +5 -0
- package/repos/effect/.changeset/fix-remainder-scientific-notation.md +5 -0
- package/repos/effect/.changeset/fix-request-resolver-pending-batches-leak.md +5 -0
- package/repos/effect/.changeset/fix-retry-transient-autocomplete.md +5 -0
- package/repos/effect/.changeset/fix-rpc-http-requestids-finalizer.md +5 -0
- package/repos/effect/.changeset/fix-rpc-json-id-edges.md +5 -0
- package/repos/effect/.changeset/fix-schedule-fixed-double-exec.md +9 -0
- package/repos/effect/.changeset/fix-schedule-reduce-sync-state.md +5 -0
- package/repos/effect/.changeset/fix-schema-arbitrary-exclusive-bounds.md +5 -0
- package/repos/effect/.changeset/fix-schema-defect-message.md +5 -0
- package/repos/effect/.changeset/fix-schema-encode-keys-property-keys.md +5 -0
- package/repos/effect/.changeset/fix-schema-encodekeys-class.md +5 -0
- package/repos/effect/.changeset/fix-schema-encodekeys-struct.md +5 -0
- package/repos/effect/.changeset/fix-schema-identifier-expected-message.md +5 -0
- package/repos/effect/.changeset/fix-schema-is-uuid.md +5 -0
- package/repos/effect/.changeset/fix-schema-option-non-schema-failures.md +17 -0
- package/repos/effect/.changeset/fix-schema-parser-checks.md +9 -0
- package/repos/effect/.changeset/fix-searchparam-initial-decode.md +5 -0
- package/repos/effect/.changeset/fix-serializable-wire-transfer.md +7 -0
- package/repos/effect/.changeset/fix-stream-grouped-within-flush.md +5 -0
- package/repos/effect/.changeset/fix-stream-run-for-each-while.md +5 -0
- package/repos/effect/.changeset/fix-stream-scan-effect.md +5 -0
- package/repos/effect/.changeset/fix-stream-scoped-scope.md +5 -0
- package/repos/effect/.changeset/fix-strip-approval-artifacts-multi-round.md +13 -0
- package/repos/effect/.changeset/fix-struct-utility-types-simplify.md +5 -0
- package/repos/effect/.changeset/fix-structwithrest-index-signatures.md +6 -0
- package/repos/effect/.changeset/fix-tagged-union-class-sentinels.md +5 -0
- package/repos/effect/.changeset/fix-tagged-union-match-unify.md +6 -0
- package/repos/effect/.changeset/fix-to-tagged-union-isanyof-custom-tags.md +10 -0
- package/repos/effect/.changeset/fix-tuple-with-rest-post-rest-index-drift.md +5 -0
- package/repos/effect/.changeset/fix-tuple-with-rest-post-rest-validation.md +5 -0
- package/repos/effect/.changeset/fix-types-voidifempty.md +5 -0
- package/repos/effect/.changeset/fix-void-response-encoding.md +5 -0
- package/repos/effect/.changeset/fix-workflow-proxy-rpc-handler-context.md +5 -0
- package/repos/effect/.changeset/flat-chicken-remain.md +5 -0
- package/repos/effect/.changeset/floppy-cows-spend.md +5 -0
- package/repos/effect/.changeset/floppy-items-admire.md +5 -0
- package/repos/effect/.changeset/floppy-pigs-kiss.md +5 -0
- package/repos/effect/.changeset/fluffy-meals-matter.md +5 -0
- package/repos/effect/.changeset/fluffy-pumas-push.md +5 -0
- package/repos/effect/.changeset/forked-memo-maps.md +6 -0
- package/repos/effect/.changeset/forty-hounds-cheer.md +5 -0
- package/repos/effect/.changeset/forty-otters-cry.md +5 -0
- package/repos/effect/.changeset/forty-rings-film.md +7 -0
- package/repos/effect/.changeset/forty-signs-stay.md +5 -0
- package/repos/effect/.changeset/forty-swans-divide.md +5 -0
- package/repos/effect/.changeset/forty-trees-pay.md +5 -0
- package/repos/effect/.changeset/four-papayas-bow.md +5 -0
- package/repos/effect/.changeset/four-points-repeat.md +5 -0
- package/repos/effect/.changeset/fresh-cats-smash.md +5 -0
- package/repos/effect/.changeset/fresh-emus-cheat.md +5 -0
- package/repos/effect/.changeset/fresh-monkeys-smoke.md +9 -0
- package/repos/effect/.changeset/fruity-houses-learn.md +6 -0
- package/repos/effect/.changeset/full-adults-double.md +5 -0
- package/repos/effect/.changeset/funny-crabs-hang.md +6 -0
- package/repos/effect/.changeset/funny-forks-move.md +5 -0
- package/repos/effect/.changeset/fuzzy-camels-hunt.md +5 -0
- package/repos/effect/.changeset/fuzzy-dodos-help.md +5 -0
- package/repos/effect/.changeset/fuzzy-lions-perform.md +5 -0
- package/repos/effect/.changeset/fuzzy-planets-sneeze.md +5 -0
- package/repos/effect/.changeset/gold-meteors-move.md +5 -0
- package/repos/effect/.changeset/gold-readers-hug.md +5 -0
- package/repos/effect/.changeset/gold-rings-start.md +5 -0
- package/repos/effect/.changeset/good-tools-work.md +7 -0
- package/repos/effect/.changeset/graph-algorithm-fixes.md +5 -0
- package/repos/effect/.changeset/great-trains-mate.md +5 -0
- package/repos/effect/.changeset/great-trams-report.md +5 -0
- package/repos/effect/.changeset/green-beds-unref.md +7 -0
- package/repos/effect/.changeset/green-chips-wash.md +5 -0
- package/repos/effect/.changeset/green-moons-smile.md +5 -0
- package/repos/effect/.changeset/green-pugs-play.md +5 -0
- package/repos/effect/.changeset/green-rings-prove.md +5 -0
- package/repos/effect/.changeset/happy-mirrors-dream.md +5 -0
- package/repos/effect/.changeset/heavy-loops-cut.md +5 -0
- package/repos/effect/.changeset/heavy-trams-fix.md +5 -0
- package/repos/effect/.changeset/hip-socks-travel.md +5 -0
- package/repos/effect/.changeset/honest-pens-thank.md +5 -0
- package/repos/effect/.changeset/honest-rivers-notice.md +5 -0
- package/repos/effect/.changeset/hot-taxis-fry.md +5 -0
- package/repos/effect/.changeset/httpapi-endpoint-relax-constraints.md +5 -0
- package/repos/effect/.changeset/httpapi-schema-service-types.md +6 -0
- package/repos/effect/.changeset/huge-moons-rhyme.md +5 -0
- package/repos/effect/.changeset/humble-pigs-dig.md +5 -0
- package/repos/effect/.changeset/icy-flies-cross.md +5 -0
- package/repos/effect/.changeset/itchy-radios-poke.md +5 -0
- package/repos/effect/.changeset/itchy-results-bet.md +5 -0
- package/repos/effect/.changeset/itchy-shrimps-deny.md +5 -0
- package/repos/effect/.changeset/itchy-toes-promise.md +5 -0
- package/repos/effect/.changeset/k8s-last-transition-null.md +5 -0
- package/repos/effect/.changeset/khaki-cats-learn.md +5 -0
- package/repos/effect/.changeset/khaki-melons-appear.md +5 -0
- package/repos/effect/.changeset/kind-hounds-float.md +5 -0
- package/repos/effect/.changeset/kind-windows-fall.md +5 -0
- package/repos/effect/.changeset/late-hotels-rule.md +5 -0
- package/repos/effect/.changeset/late-lamps-care.md +5 -0
- package/repos/effect/.changeset/late-rivers-applaud.md +5 -0
- package/repos/effect/.changeset/layer-map-dynamic-idle-ttl.md +5 -0
- package/repos/effect/.changeset/lazy-queens-rush.md +5 -0
- package/repos/effect/.changeset/lazy-recursive-forward-refs.md +5 -0
- package/repos/effect/.changeset/lazy-timers-exist.md +5 -0
- package/repos/effect/.changeset/legal-pants-drop.md +5 -0
- package/repos/effect/.changeset/lemon-taxis-sin.md +5 -0
- package/repos/effect/.changeset/light-kids-sneeze.md +5 -0
- package/repos/effect/.changeset/little-dryers-allow.md +7 -0
- package/repos/effect/.changeset/long-cameras-think.md +5 -0
- package/repos/effect/.changeset/lovely-cobras-change.md +5 -0
- package/repos/effect/.changeset/lovely-frogs-rescue.md +5 -0
- package/repos/effect/.changeset/lucky-buttons-jump.md +5 -0
- package/repos/effect/.changeset/lucky-phones-listen.md +5 -0
- package/repos/effect/.changeset/lucky-worms-type.md +5 -0
- package/repos/effect/.changeset/mean-dingos-share.md +5 -0
- package/repos/effect/.changeset/mean-trains-smash.md +5 -0
- package/repos/effect/.changeset/metal-parts-yell.md +5 -0
- package/repos/effect/.changeset/mighty-games-matter.md +5 -0
- package/repos/effect/.changeset/modern-uuid-guid-filter.md +5 -0
- package/repos/effect/.changeset/nasty-geese-grow.md +5 -0
- package/repos/effect/.changeset/neat-goats-wave.md +5 -0
- package/repos/effect/.changeset/neat-kings-chew.md +5 -0
- package/repos/effect/.changeset/neat-lions-rest.md +5 -0
- package/repos/effect/.changeset/neat-snails-wash.md +5 -0
- package/repos/effect/.changeset/neat-taxis-notice.md +5 -0
- package/repos/effect/.changeset/new-dogs-swim.md +5 -0
- package/repos/effect/.changeset/new-toes-stop.md +5 -0
- package/repos/effect/.changeset/ninety-geese-exist.md +5 -0
- package/repos/effect/.changeset/odd-boats-think.md +5 -0
- package/repos/effect/.changeset/odd-bulldogs-sleep.md +5 -0
- package/repos/effect/.changeset/odd-fans-glow.md +5 -0
- package/repos/effect/.changeset/odd-forks-talk.md +5 -0
- package/repos/effect/.changeset/odd-laws-draw.md +5 -0
- package/repos/effect/.changeset/odd-owls-smoke.md +5 -0
- package/repos/effect/.changeset/odd-socks-boil.md +5 -0
- package/repos/effect/.changeset/odd-suns-dance.md +5 -0
- package/repos/effect/.changeset/old-brooms-cry.md +5 -0
- package/repos/effect/.changeset/old-facts-stand.md +5 -0
- package/repos/effect/.changeset/old-mirrors-float.md +5 -0
- package/repos/effect/.changeset/olive-poems-visit.md +5 -0
- package/repos/effect/.changeset/open-hotels-remain.md +5 -0
- package/repos/effect/.changeset/openai-compat-nullable-tool-name.md +7 -0
- package/repos/effect/.changeset/openai-compat-reasoning.md +5 -0
- package/repos/effect/.changeset/otel-resource-env-precedence.md +5 -0
- package/repos/effect/.changeset/perfect-buckets-tickle.md +5 -0
- package/repos/effect/.changeset/petite-months-allow.md +6 -0
- package/repos/effect/.changeset/platform-crypto-service.md +9 -0
- package/repos/effect/.changeset/platform-node-shared-barrel.md +5 -0
- package/repos/effect/.changeset/plenty-moons-pull.md +5 -0
- package/repos/effect/.changeset/polite-brooms-tickle.md +5 -0
- package/repos/effect/.changeset/polite-pigs-speak.md +5 -0
- package/repos/effect/.changeset/polite-tables-kneel.md +5 -0
- package/repos/effect/.changeset/port-react-hydration.md +8 -0
- package/repos/effect/.changeset/pre.json +588 -0
- package/repos/effect/.changeset/public-deer-ring.md +5 -0
- package/repos/effect/.changeset/public-jeans-stop.md +5 -0
- package/repos/effect/.changeset/pubsub-publish-false.md +5 -0
- package/repos/effect/.changeset/puny-pens-clap.md +6 -0
- package/repos/effect/.changeset/purple-bars-prove.md +5 -0
- package/repos/effect/.changeset/purple-schools-float.md +5 -0
- package/repos/effect/.changeset/purple-turtles-draw.md +5 -0
- package/repos/effect/.changeset/quick-dragons-fix.md +5 -0
- package/repos/effect/.changeset/quick-falcons-travel.md +5 -0
- package/repos/effect/.changeset/quick-geese-relax.md +5 -0
- package/repos/effect/.changeset/quick-lamps-dig.md +5 -0
- package/repos/effect/.changeset/quick-lizards-fall.md +5 -0
- package/repos/effect/.changeset/quick-trees-join.md +5 -0
- package/repos/effect/.changeset/quiet-carpets-grin.md +5 -0
- package/repos/effect/.changeset/quiet-files-hunt.md +5 -0
- package/repos/effect/.changeset/quiet-lamps-jam.md +5 -0
- package/repos/effect/.changeset/quiet-radios-wave.md +5 -0
- package/repos/effect/.changeset/quiet-redis-scripts.md +5 -0
- package/repos/effect/.changeset/ready-olives-divide.md +5 -0
- package/repos/effect/.changeset/real-trains-ring.md +5 -0
- package/repos/effect/.changeset/red-pigs-repair.md +5 -0
- package/repos/effect/.changeset/redacted-representation-options.md +7 -0
- package/repos/effect/.changeset/refactor-cli-global-flags.md +27 -0
- package/repos/effect/.changeset/refactor-config-provider.md +23 -0
- package/repos/effect/.changeset/refactor-representation-references.md +5 -0
- package/repos/effect/.changeset/remove-effect-transactionwith.md +5 -0
- package/repos/effect/.changeset/remove-http-span-counter.md +5 -0
- package/repos/effect/.changeset/remove-nullor.md +5 -0
- package/repos/effect/.changeset/remove-openapi-fromapi-options.md +7 -0
- package/repos/effect/.changeset/remove-types-mergerecord.md +5 -0
- package/repos/effect/.changeset/remove-unused-utils-apis.md +5 -0
- package/repos/effect/.changeset/rename-rebuild-out.md +5 -0
- package/repos/effect/.changeset/restore-schema-parse-options.md +5 -0
- package/repos/effect/.changeset/rich-dots-push.md +5 -0
- package/repos/effect/.changeset/rich-hoops-nail.md +5 -0
- package/repos/effect/.changeset/rich-sloths-draw.md +5 -0
- package/repos/effect/.changeset/ripe-lies-battle.md +5 -0
- package/repos/effect/.changeset/rpc-middleware-provides-fix.md +5 -0
- package/repos/effect/.changeset/scalar-custom-fetch.md +5 -0
- package/repos/effect/.changeset/schema-as-class.md +17 -0
- package/repos/effect/.changeset/schema-asserts-signature.md +5 -0
- package/repos/effect/.changeset/schema-clean-up-additionalProperties.md +7 -0
- package/repos/effect/.changeset/schema-datetime-utc-from-string.md +5 -0
- package/repos/effect/.changeset/schema-decoding-defaults-services.md +7 -0
- package/repos/effect/.changeset/schema-defaults-issue-channel.md +7 -0
- package/repos/effect/.changeset/schema-dollar-prefix.md +5 -0
- package/repos/effect/.changeset/schema-missing-self-generic.md +5 -0
- package/repos/effect/.changeset/schema-ordered-arbitrary-constraints.md +12 -0
- package/repos/effect/.changeset/schema-parser-adapter-errors.md +5 -0
- package/repos/effect/.changeset/schema-refactor-toCodecJson.md +5 -0
- package/repos/effect/.changeset/schema-remove-annotate-in.md +5 -0
- package/repos/effect/.changeset/schema-rename-makeUnsafe-to-make.md +7 -0
- package/repos/effect/.changeset/schema-rename-parser-makeUnsafe.md +5 -0
- package/repos/effect/.changeset/schema-result-combinators.md +5 -0
- package/repos/effect/.changeset/schema-struct-simplify.md +5 -0
- package/repos/effect/.changeset/seven-mugs-marry.md +5 -0
- package/repos/effect/.changeset/shaggy-birds-stay.md +5 -0
- package/repos/effect/.changeset/shaggy-cities-push.md +5 -0
- package/repos/effect/.changeset/shaggy-numbers-accept.md +5 -0
- package/repos/effect/.changeset/sharp-emus-applaud.md +5 -0
- package/repos/effect/.changeset/sharp-goats-wink.md +5 -0
- package/repos/effect/.changeset/sharp-pandas-care.md +5 -0
- package/repos/effect/.changeset/sharp-peas-march.md +5 -0
- package/repos/effect/.changeset/sharp-rules-draw.md +5 -0
- package/repos/effect/.changeset/sharp-singers-sort.md +5 -0
- package/repos/effect/.changeset/shiny-trains-hug.md +5 -0
- package/repos/effect/.changeset/short-cows-relate.md +5 -0
- package/repos/effect/.changeset/short-foxes-admire.md +5 -0
- package/repos/effect/.changeset/shy-cycles-flow.md +5 -0
- package/repos/effect/.changeset/shy-geckos-sniff.md +30 -0
- package/repos/effect/.changeset/silent-geckos-matter.md +5 -0
- package/repos/effect/.changeset/silent-needles-design.md +6 -0
- package/repos/effect/.changeset/silent-plants-matter.md +8 -0
- package/repos/effect/.changeset/silent-spoons-stare.md +5 -0
- package/repos/effect/.changeset/silly-loops-tickle.md +5 -0
- package/repos/effect/.changeset/silver-bulk-indexeddb.md +5 -0
- package/repos/effect/.changeset/silver-emus-smoke.md +5 -0
- package/repos/effect/.changeset/silver-kings-poke.md +5 -0
- package/repos/effect/.changeset/silver-snails-sqlite.md +17 -0
- package/repos/effect/.changeset/silver-wings-watch.md +5 -0
- package/repos/effect/.changeset/six-cups-taste.md +5 -0
- package/repos/effect/.changeset/sixty-mails-shout.md +5 -0
- package/repos/effect/.changeset/sixty-socks-yell.md +5 -0
- package/repos/effect/.changeset/slimy-planets-divide.md +5 -0
- package/repos/effect/.changeset/slimy-turtles-juggle.md +5 -0
- package/repos/effect/.changeset/slow-beans-battle.md +28 -0
- package/repos/effect/.changeset/slow-berries-enjoy.md +5 -0
- package/repos/effect/.changeset/small-bugs-hunt.md +5 -0
- package/repos/effect/.changeset/small-crabs-care.md +9 -0
- package/repos/effect/.changeset/small-pets-sit.md +6 -0
- package/repos/effect/.changeset/smart-ducks-jump.md +6 -0
- package/repos/effect/.changeset/smart-pillows-buy.md +6 -0
- package/repos/effect/.changeset/smart-timers-fly.md +5 -0
- package/repos/effect/.changeset/smart-tips-sort.md +5 -0
- package/repos/effect/.changeset/social-pumas-prove.md +5 -0
- package/repos/effect/.changeset/soft-comics-wink.md +5 -0
- package/repos/effect/.changeset/soft-delete-sqlmodel.md +5 -0
- package/repos/effect/.changeset/soft-seals-allow.md +5 -0
- package/repos/effect/.changeset/solid-cougars-attack.md +5 -0
- package/repos/effect/.changeset/solid-doors-ring.md +5 -0
- package/repos/effect/.changeset/solid-items-tease.md +5 -0
- package/repos/effect/.changeset/solid-towns-smoke.md +5 -0
- package/repos/effect/.changeset/sour-canyons-rescue.md +5 -0
- package/repos/effect/.changeset/sparkly-bears-act.md +5 -0
- package/repos/effect/.changeset/sparkly-coins-sit.md +5 -0
- package/repos/effect/.changeset/spotty-comics-fry.md +5 -0
- package/repos/effect/.changeset/sql-migrator-mjs-mts.md +5 -0
- package/repos/effect/.changeset/stale-dots-tell.md +5 -0
- package/repos/effect/.changeset/stale-snakes-know.md +5 -0
- package/repos/effect/.changeset/strict-areas-end.md +5 -0
- package/repos/effect/.changeset/strict-buckets-hug.md +8 -0
- package/repos/effect/.changeset/strip-resolved-approvals.md +5 -0
- package/repos/effect/.changeset/strong-balloons-tickle.md +5 -0
- package/repos/effect/.changeset/strong-bees-queue.md +5 -0
- package/repos/effect/.changeset/struct-record.md +5 -0
- package/repos/effect/.changeset/sunny-ads-hang.md +5 -0
- package/repos/effect/.changeset/sunny-bikes-sleep.md +5 -0
- package/repos/effect/.changeset/sunny-rooms-invent.md +5 -0
- package/repos/effect/.changeset/sweet-donuts-bet.md +5 -0
- package/repos/effect/.changeset/sweet-hotels-give.md +5 -0
- package/repos/effect/.changeset/sweet-views-learn.md +5 -0
- package/repos/effect/.changeset/swift-spiders-unpack.md +5 -0
- package/repos/effect/.changeset/swift-symbols-stand.md +5 -0
- package/repos/effect/.changeset/tagged-error-class-optional-empty-props.md +5 -0
- package/repos/effect/.changeset/tall-hairs-return.md +5 -0
- package/repos/effect/.changeset/tall-mails-listen.md +5 -0
- package/repos/effect/.changeset/tall-queens-cheer.md +5 -0
- package/repos/effect/.changeset/tall-wombats-wave.md +5 -0
- package/repos/effect/.changeset/tangy-colts-lose.md +5 -0
- package/repos/effect/.changeset/tasty-comics-send.md +5 -0
- package/repos/effect/.changeset/ten-kings-fry.md +5 -0
- package/repos/effect/.changeset/thick-pandas-wait.md +5 -0
- package/repos/effect/.changeset/thin-ducks-wonder.md +5 -0
- package/repos/effect/.changeset/thirty-ducks-go.md +5 -0
- package/repos/effect/.changeset/thirty-pans-love.md +5 -0
- package/repos/effect/.changeset/three-corners-sort.md +5 -0
- package/repos/effect/.changeset/three-ravens-jam.md +5 -0
- package/repos/effect/.changeset/three-tomatoes-wave.md +5 -0
- package/repos/effect/.changeset/tidy-foxes-own.md +5 -0
- package/repos/effect/.changeset/tidy-icons-glow.md +5 -0
- package/repos/effect/.changeset/tidy-stacks-encode.md +5 -0
- package/repos/effect/.changeset/tidy-stars-drive.md +5 -0
- package/repos/effect/.changeset/tiny-buckets-wave.md +5 -0
- package/repos/effect/.changeset/tiny-lilies-flash.md +5 -0
- package/repos/effect/.changeset/tiny-rabbits-smile.md +5 -0
- package/repos/effect/.changeset/tocodecjson-return-json-type.md +10 -0
- package/repos/effect/.changeset/tool-get-json-schema-tests.md +5 -0
- package/repos/effect/.changeset/true-actors-battle.md +5 -0
- package/repos/effect/.changeset/twenty-buttons-cheer.md +5 -0
- package/repos/effect/.changeset/two-roses-double.md +5 -0
- package/repos/effect/.changeset/unify-error-defect-stack-options.md +23 -0
- package/repos/effect/.changeset/update-schema-arbitrary-report.md +22 -0
- package/repos/effect/.changeset/upset-colts-stick.md +5 -0
- package/repos/effect/.changeset/vast-bananas-send.md +5 -0
- package/repos/effect/.changeset/vast-deserts-travel.md +5 -0
- package/repos/effect/.changeset/violet-peaches-feel.md +5 -0
- package/repos/effect/.changeset/vitest-layer-top-level-options.md +5 -0
- package/repos/effect/.changeset/wacky-grapes-poke.md +5 -0
- package/repos/effect/.changeset/wacky-rice-add.md +5 -0
- package/repos/effect/.changeset/warm-dolls-brake.md +5 -0
- package/repos/effect/.changeset/warm-friends-tie.md +5 -0
- package/repos/effect/.changeset/warm-snails-shop.md +7 -0
- package/repos/effect/.changeset/wet-news-invent.md +5 -0
- package/repos/effect/.changeset/wild-readers-clean.md +5 -0
- package/repos/effect/.changeset/wild-suns-bearer-space.md +5 -0
- package/repos/effect/.changeset/wise-ants-wave.md +6 -0
- package/repos/effect/.changeset/wise-flags-shift.md +22 -0
- package/repos/effect/.changeset/wise-oranges-stay.md +5 -0
- package/repos/effect/.changeset/witty-lobsters-share.md +5 -0
- package/repos/effect/.changeset/yellow-adults-study.md +5 -0
- package/repos/effect/.changeset/yellow-clocks-dance.md +5 -0
- package/repos/effect/.changeset/yellow-dingos-jump.md +5 -0
- package/repos/effect/.changeset/young-doors-change.md +5 -0
- package/repos/effect/.envrc +1 -0
- package/repos/effect/.github/actions/setup/action.yaml +33 -0
- package/repos/effect/.github/workflows/ai-codegen.yml +66 -0
- package/repos/effect/.github/workflows/bundle-comment.yml +72 -0
- package/repos/effect/.github/workflows/check.yml +195 -0
- package/repos/effect/.github/workflows/release.yml +47 -0
- package/repos/effect/.github/workflows/snapshot.yml +34 -0
- package/repos/effect/.oxlintrc.json +25 -0
- package/repos/effect/.patterns/effect.md +102 -0
- package/repos/effect/.patterns/jsdoc.md +53 -0
- package/repos/effect/.patterns/testing.md +44 -0
- package/repos/effect/.specs/README.md +2 -0
- package/repos/effect/.vscode/extensions.json +6 -0
- package/repos/effect/.vscode/settings.json +44 -0
- package/repos/effect/AGENTS.md +139 -0
- package/repos/effect/LICENSE +21 -0
- package/repos/effect/LLMS.md +343 -0
- package/repos/effect/MIGRATION.md +83 -0
- package/repos/effect/README.md +3 -0
- package/repos/effect/TODOS.md +28 -0
- package/repos/effect/ai-docs/README.md +44 -0
- package/repos/effect/ai-docs/package.json +36 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/01_effect-gen.ts +30 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +39 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/10_creating-effects.ts +74 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/index.md +5 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/01_service.ts +45 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/10_reference.ts +10 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/20_layer-composition.ts +70 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/20_layer-unwrap.ts +66 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/index.md +5 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/01_error-handling.ts +30 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/10_catch-tags.ts +24 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/20_reason-errors.ts +64 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/index.md +1 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/10_acquire-release.ts +105 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/20_layer-side-effects.ts +31 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/30_layer-map.ts +86 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/index.md +3 -0
- package/repos/effect/ai-docs/src/01_effect/05_running/10_run-main.ts +30 -0
- package/repos/effect/ai-docs/src/01_effect/05_running/20_layer-launch.ts +27 -0
- package/repos/effect/ai-docs/src/01_effect/05_running/index.md +1 -0
- package/repos/effect/ai-docs/src/01_effect/06_pubsub/10_pubsub.ts +56 -0
- package/repos/effect/ai-docs/src/01_effect/06_pubsub/index.md +3 -0
- package/repos/effect/ai-docs/src/02_stream/10_creating-streams.ts +103 -0
- package/repos/effect/ai-docs/src/02_stream/20_consuming-streams.ts +137 -0
- package/repos/effect/ai-docs/src/02_stream/30_encoding.ts +165 -0
- package/repos/effect/ai-docs/src/02_stream/index.md +4 -0
- package/repos/effect/ai-docs/src/03_integration/10_managed-runtime.ts +129 -0
- package/repos/effect/ai-docs/src/03_integration/index.md +5 -0
- package/repos/effect/ai-docs/src/05_batching/10_request-resolver.ts +89 -0
- package/repos/effect/ai-docs/src/05_batching/index.md +3 -0
- package/repos/effect/ai-docs/src/06_schedule/10_schedules.ts +102 -0
- package/repos/effect/ai-docs/src/06_schedule/index.md +3 -0
- package/repos/effect/ai-docs/src/07_datetime/10_creating-and-formatting.ts +30 -0
- package/repos/effect/ai-docs/src/07_datetime/20_time-zones.ts +44 -0
- package/repos/effect/ai-docs/src/07_datetime/index.md +5 -0
- package/repos/effect/ai-docs/src/08_observability/10_logging.ts +66 -0
- package/repos/effect/ai-docs/src/08_observability/20_otlp-tracing.ts +95 -0
- package/repos/effect/ai-docs/src/08_observability/index.md +7 -0
- package/repos/effect/ai-docs/src/09_testing/10_effect-tests.ts +55 -0
- package/repos/effect/ai-docs/src/09_testing/20_layer-tests.ts +138 -0
- package/repos/effect/ai-docs/src/09_testing/index.md +1 -0
- package/repos/effect/ai-docs/src/50_http-client/10_basics.ts +102 -0
- package/repos/effect/ai-docs/src/50_http-client/index.md +3 -0
- package/repos/effect/ai-docs/src/51_http-server/10_basics.ts +116 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/Api.ts +14 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/Authorization.ts +36 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/System.ts +10 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/Users.ts +91 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/domain/User.ts +12 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/domain/UserErrors.ts +22 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +36 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +71 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/server/Users.ts +62 -0
- package/repos/effect/ai-docs/src/51_http-server/index.md +3 -0
- package/repos/effect/ai-docs/src/60_child-process/10_working-with-child-processes.ts +117 -0
- package/repos/effect/ai-docs/src/60_child-process/index.md +3 -0
- package/repos/effect/ai-docs/src/70_cli/10_basics.ts +136 -0
- package/repos/effect/ai-docs/src/70_cli/index.md +5 -0
- package/repos/effect/ai-docs/src/71_ai/10_language-model.ts +156 -0
- package/repos/effect/ai-docs/src/71_ai/20_tools.ts +226 -0
- package/repos/effect/ai-docs/src/71_ai/30_chat.ts +158 -0
- package/repos/effect/ai-docs/src/71_ai/fixtures/domain/LaunchPlan.ts +9 -0
- package/repos/effect/ai-docs/src/71_ai/index.md +5 -0
- package/repos/effect/ai-docs/src/80_cluster/10_entities.ts +97 -0
- package/repos/effect/ai-docs/src/80_cluster/index.md +4 -0
- package/repos/effect/ai-docs/src/index.md +12 -0
- package/repos/effect/ai-docs/tsconfig.json +24 -0
- package/repos/effect/cookbooks/schedule.md +3507 -0
- package/repos/effect/deno.json +33 -0
- package/repos/effect/docker-compose.yaml +18 -0
- package/repos/effect/dprint.json +32 -0
- package/repos/effect/flake.lock +27 -0
- package/repos/effect/flake.nix +24 -0
- package/repos/effect/jsdocs.config.json +16 -0
- package/repos/effect/migration/cause.md +163 -0
- package/repos/effect/migration/equality.md +72 -0
- package/repos/effect/migration/error-handling.md +106 -0
- package/repos/effect/migration/fiber-keep-alive.md +74 -0
- package/repos/effect/migration/fiberref.md +109 -0
- package/repos/effect/migration/forking.md +94 -0
- package/repos/effect/migration/generators.md +32 -0
- package/repos/effect/migration/layer-memoization.md +98 -0
- package/repos/effect/migration/runtime.md +88 -0
- package/repos/effect/migration/schema.md +1032 -0
- package/repos/effect/migration/scope.md +50 -0
- package/repos/effect/migration/services.md +235 -0
- package/repos/effect/migration/v3-to-v4.md +421 -0
- package/repos/effect/migration/yieldable.md +173 -0
- package/repos/effect/package.json +104 -0
- package/repos/effect/packages/ai/anthropic/CHANGELOG.md +611 -0
- package/repos/effect/packages/ai/anthropic/codegen.yml +63 -0
- package/repos/effect/packages/ai/anthropic/docgen.json +26 -0
- package/repos/effect/packages/ai/anthropic/package.json +67 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicClient.ts +432 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicConfig.ts +84 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicError.ts +212 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicLanguageModel.ts +3098 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicTelemetry.ts +132 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicTool.ts +2512 -0
- package/repos/effect/packages/ai/anthropic/src/Generated.ts +12600 -0
- package/repos/effect/packages/ai/anthropic/src/index.ts +40 -0
- package/repos/effect/packages/ai/anthropic/src/internal/errors.ts +370 -0
- package/repos/effect/packages/ai/anthropic/src/internal/utilities.ts +26 -0
- package/repos/effect/packages/ai/anthropic/test/AnthropicLanguageModel.test.ts +300 -0
- package/repos/effect/packages/ai/anthropic/tsconfig.json +8 -0
- package/repos/effect/packages/ai/anthropic/vitest.config.ts +6 -0
- package/repos/effect/packages/ai/openai/CHANGELOG.md +668 -0
- package/repos/effect/packages/ai/openai/codegen.yaml +41 -0
- package/repos/effect/packages/ai/openai/docgen.json +24 -0
- package/repos/effect/packages/ai/openai/package.json +67 -0
- package/repos/effect/packages/ai/openai/src/Generated.ts +35774 -0
- package/repos/effect/packages/ai/openai/src/OpenAiClient.ts +730 -0
- package/repos/effect/packages/ai/openai/src/OpenAiClientGenerated.ts +202 -0
- package/repos/effect/packages/ai/openai/src/OpenAiConfig.ts +93 -0
- package/repos/effect/packages/ai/openai/src/OpenAiEmbeddingModel.ts +258 -0
- package/repos/effect/packages/ai/openai/src/OpenAiError.ts +242 -0
- package/repos/effect/packages/ai/openai/src/OpenAiLanguageModel.ts +3133 -0
- package/repos/effect/packages/ai/openai/src/OpenAiSchema.ts +1286 -0
- package/repos/effect/packages/ai/openai/src/OpenAiTelemetry.ts +162 -0
- package/repos/effect/packages/ai/openai/src/OpenAiTool.ts +342 -0
- package/repos/effect/packages/ai/openai/src/index.ts +55 -0
- package/repos/effect/packages/ai/openai/src/internal/errors.ts +349 -0
- package/repos/effect/packages/ai/openai/src/internal/utilities.ts +33 -0
- package/repos/effect/packages/ai/openai/test/OpenAiClient.test.ts +798 -0
- package/repos/effect/packages/ai/openai/test/OpenAiEmbeddingModel.test.ts +289 -0
- package/repos/effect/packages/ai/openai/test/OpenAiLanguageModel.test.ts +1528 -0
- package/repos/effect/packages/ai/openai/test/OpenAiSchema.test.ts +273 -0
- package/repos/effect/packages/ai/openai/tsconfig.json +8 -0
- package/repos/effect/packages/ai/openai/vitest.config.ts +6 -0
- package/repos/effect/packages/ai/openai-compat/CHANGELOG.md +626 -0
- package/repos/effect/packages/ai/openai-compat/docgen.json +24 -0
- package/repos/effect/packages/ai/openai-compat/package.json +69 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiClient.ts +1221 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiConfig.ts +87 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiEmbeddingModel.ts +254 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiError.ts +178 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiLanguageModel.ts +1951 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiTelemetry.ts +164 -0
- package/repos/effect/packages/ai/openai-compat/src/index.ts +35 -0
- package/repos/effect/packages/ai/openai-compat/src/internal/errors.ts +327 -0
- package/repos/effect/packages/ai/openai-compat/src/internal/utilities.ts +33 -0
- package/repos/effect/packages/ai/openai-compat/test/OpenAiClient.test.ts +474 -0
- package/repos/effect/packages/ai/openai-compat/test/OpenAiEmbeddingModel.test.ts +216 -0
- package/repos/effect/packages/ai/openai-compat/test/OpenAiLanguageModel.test.ts +1505 -0
- package/repos/effect/packages/ai/openai-compat/tsconfig.json +8 -0
- package/repos/effect/packages/ai/openai-compat/vitest.config.ts +6 -0
- package/repos/effect/packages/ai/openrouter/CHANGELOG.md +607 -0
- package/repos/effect/packages/ai/openrouter/codegen.yml +35 -0
- package/repos/effect/packages/ai/openrouter/docgen.json +24 -0
- package/repos/effect/packages/ai/openrouter/package.json +67 -0
- package/repos/effect/packages/ai/openrouter/src/Generated.ts +10028 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterClient.ts +357 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterConfig.ts +99 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterError.ts +225 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterLanguageModel.ts +1796 -0
- package/repos/effect/packages/ai/openrouter/src/index.ts +30 -0
- package/repos/effect/packages/ai/openrouter/src/internal/errors.ts +375 -0
- package/repos/effect/packages/ai/openrouter/src/internal/utilities.ts +92 -0
- package/repos/effect/packages/ai/openrouter/tsconfig.json +10 -0
- package/repos/effect/packages/ai/openrouter/vitest.config.ts +6 -0
- package/repos/effect/packages/atom/react/CHANGELOG.md +599 -0
- package/repos/effect/packages/atom/react/LICENSE +21 -0
- package/repos/effect/packages/atom/react/README.md +7 -0
- package/repos/effect/packages/atom/react/docgen.json +25 -0
- package/repos/effect/packages/atom/react/package.json +79 -0
- package/repos/effect/packages/atom/react/src/Hooks.ts +476 -0
- package/repos/effect/packages/atom/react/src/ReactHydration.ts +109 -0
- package/repos/effect/packages/atom/react/src/RegistryContext.ts +108 -0
- package/repos/effect/packages/atom/react/src/ScopedAtom.ts +151 -0
- package/repos/effect/packages/atom/react/src/index.ts +23 -0
- package/repos/effect/packages/atom/react/test/index.test.tsx +650 -0
- package/repos/effect/packages/atom/react/tsconfig.json +8 -0
- package/repos/effect/packages/atom/react/vitest.config.ts +9 -0
- package/repos/effect/packages/atom/react/vitest.setup.ts +8 -0
- package/repos/effect/packages/atom/solid/CHANGELOG.md +595 -0
- package/repos/effect/packages/atom/solid/LICENSE +21 -0
- package/repos/effect/packages/atom/solid/README.md +7 -0
- package/repos/effect/packages/atom/solid/docgen.json +26 -0
- package/repos/effect/packages/atom/solid/package.json +72 -0
- package/repos/effect/packages/atom/solid/src/Hooks.ts +359 -0
- package/repos/effect/packages/atom/solid/src/RegistryContext.ts +80 -0
- package/repos/effect/packages/atom/solid/src/index.ts +13 -0
- package/repos/effect/packages/atom/solid/test/index.test.tsx +296 -0
- package/repos/effect/packages/atom/solid/tsconfig.json +8 -0
- package/repos/effect/packages/atom/solid/vitest.config.ts +15 -0
- package/repos/effect/packages/atom/solid/vitest.setup.ts +8 -0
- package/repos/effect/packages/atom/vue/CHANGELOG.md +593 -0
- package/repos/effect/packages/atom/vue/LICENSE +21 -0
- package/repos/effect/packages/atom/vue/README.md +7 -0
- package/repos/effect/packages/atom/vue/docgen.json +24 -0
- package/repos/effect/packages/atom/vue/package.json +68 -0
- package/repos/effect/packages/atom/vue/src/index.ts +211 -0
- package/repos/effect/packages/atom/vue/test/index.test.ts +5 -0
- package/repos/effect/packages/atom/vue/tsconfig.json +14 -0
- package/repos/effect/packages/atom/vue/vitest.config.ts +8 -0
- package/repos/effect/packages/effect/CHANGELOG.md +1607 -0
- package/repos/effect/packages/effect/CONFIG.md +690 -0
- package/repos/effect/packages/effect/HTTPAPI.md +3213 -0
- package/repos/effect/packages/effect/LICENSE +21 -0
- package/repos/effect/packages/effect/MCP.md +369 -0
- package/repos/effect/packages/effect/OPTIC.md +620 -0
- package/repos/effect/packages/effect/README.md +53 -0
- package/repos/effect/packages/effect/SCHEMA.md +7284 -0
- package/repos/effect/packages/effect/benchmark/schema/Enums.ts +40 -0
- package/repos/effect/packages/effect/benchmark/schema/Optic.ts +79 -0
- package/repos/effect/packages/effect/benchmark/schema/array.ts +74 -0
- package/repos/effect/packages/effect/benchmark/schema/filter.ts +74 -0
- package/repos/effect/packages/effect/benchmark/schema/object.ts +82 -0
- package/repos/effect/packages/effect/benchmark/schema/tagged-union.ts +69 -0
- package/repos/effect/packages/effect/benchmark/schema/transformation.ts +91 -0
- package/repos/effect/packages/effect/benchmark/stream/splitLines.ts +46 -0
- package/repos/effect/packages/effect/docgen.json +38 -0
- package/repos/effect/packages/effect/package.json +127 -0
- package/repos/effect/packages/effect/src/Array.ts +4908 -0
- package/repos/effect/packages/effect/src/BigDecimal.ts +1943 -0
- package/repos/effect/packages/effect/src/BigInt.ts +1029 -0
- package/repos/effect/packages/effect/src/Boolean.ts +481 -0
- package/repos/effect/packages/effect/src/Brand.ts +318 -0
- package/repos/effect/packages/effect/src/Cache.ts +1295 -0
- package/repos/effect/packages/effect/src/Cause.ts +1939 -0
- package/repos/effect/packages/effect/src/Channel.ts +8615 -0
- package/repos/effect/packages/effect/src/ChannelSchema.ts +308 -0
- package/repos/effect/packages/effect/src/Chunk.ts +2976 -0
- package/repos/effect/packages/effect/src/Clock.ts +194 -0
- package/repos/effect/packages/effect/src/Combiner.ts +316 -0
- package/repos/effect/packages/effect/src/Config.ts +1416 -0
- package/repos/effect/packages/effect/src/ConfigProvider.ts +1159 -0
- package/repos/effect/packages/effect/src/Console.ts +653 -0
- package/repos/effect/packages/effect/src/Context.ts +1339 -0
- package/repos/effect/packages/effect/src/Cron.ts +1212 -0
- package/repos/effect/packages/effect/src/Crypto.ts +318 -0
- package/repos/effect/packages/effect/src/Data.ts +774 -0
- package/repos/effect/packages/effect/src/DateTime.ts +2922 -0
- package/repos/effect/packages/effect/src/Deferred.ts +917 -0
- package/repos/effect/packages/effect/src/Differ.ts +32 -0
- package/repos/effect/packages/effect/src/Duration.ts +1827 -0
- package/repos/effect/packages/effect/src/Effect.ts +15347 -0
- package/repos/effect/packages/effect/src/Effectable.ts +68 -0
- package/repos/effect/packages/effect/src/Encoding.ts +1046 -0
- package/repos/effect/packages/effect/src/Equal.ts +550 -0
- package/repos/effect/packages/effect/src/Equivalence.ts +870 -0
- package/repos/effect/packages/effect/src/ErrorReporter.ts +543 -0
- package/repos/effect/packages/effect/src/ExecutionPlan.ts +416 -0
- package/repos/effect/packages/effect/src/Exit.ts +1085 -0
- package/repos/effect/packages/effect/src/Fiber.ts +632 -0
- package/repos/effect/packages/effect/src/FiberHandle.ts +815 -0
- package/repos/effect/packages/effect/src/FiberMap.ts +1030 -0
- package/repos/effect/packages/effect/src/FiberSet.ts +713 -0
- package/repos/effect/packages/effect/src/FileSystem.ts +1394 -0
- package/repos/effect/packages/effect/src/Filter.ts +827 -0
- package/repos/effect/packages/effect/src/Formatter.ts +319 -0
- package/repos/effect/packages/effect/src/Function.ts +1415 -0
- package/repos/effect/packages/effect/src/Graph.ts +4892 -0
- package/repos/effect/packages/effect/src/HKT.ts +213 -0
- package/repos/effect/packages/effect/src/Hash.ts +539 -0
- package/repos/effect/packages/effect/src/HashMap.ts +1236 -0
- package/repos/effect/packages/effect/src/HashRing.ts +426 -0
- package/repos/effect/packages/effect/src/HashSet.ts +605 -0
- package/repos/effect/packages/effect/src/Inspectable.ts +329 -0
- package/repos/effect/packages/effect/src/Iterable.ts +2483 -0
- package/repos/effect/packages/effect/src/JsonPatch.ts +469 -0
- package/repos/effect/packages/effect/src/JsonPointer.ts +80 -0
- package/repos/effect/packages/effect/src/JsonSchema.ts +948 -0
- package/repos/effect/packages/effect/src/Latch.ts +373 -0
- package/repos/effect/packages/effect/src/Layer.ts +2773 -0
- package/repos/effect/packages/effect/src/LayerMap.ts +468 -0
- package/repos/effect/packages/effect/src/LogLevel.ts +412 -0
- package/repos/effect/packages/effect/src/Logger.ts +1284 -0
- package/repos/effect/packages/effect/src/ManagedRuntime.ts +381 -0
- package/repos/effect/packages/effect/src/Match.ts +2606 -0
- package/repos/effect/packages/effect/src/Metric.ts +4058 -0
- package/repos/effect/packages/effect/src/MutableHashMap.ts +845 -0
- package/repos/effect/packages/effect/src/MutableHashSet.ts +422 -0
- package/repos/effect/packages/effect/src/MutableList.ts +967 -0
- package/repos/effect/packages/effect/src/MutableRef.ts +822 -0
- package/repos/effect/packages/effect/src/Newtype.ts +319 -0
- package/repos/effect/packages/effect/src/NonEmptyIterable.ts +221 -0
- package/repos/effect/packages/effect/src/Number.ts +860 -0
- package/repos/effect/packages/effect/src/Optic.ts +1701 -0
- package/repos/effect/packages/effect/src/Option.ts +2664 -0
- package/repos/effect/packages/effect/src/Order.ts +982 -0
- package/repos/effect/packages/effect/src/Ordering.ts +182 -0
- package/repos/effect/packages/effect/src/PartitionedSemaphore.ts +561 -0
- package/repos/effect/packages/effect/src/Path.ts +870 -0
- package/repos/effect/packages/effect/src/Pipeable.ts +674 -0
- package/repos/effect/packages/effect/src/PlatformError.ts +221 -0
- package/repos/effect/packages/effect/src/Pool.ts +699 -0
- package/repos/effect/packages/effect/src/Predicate.ts +1872 -0
- package/repos/effect/packages/effect/src/PrimaryKey.ts +123 -0
- package/repos/effect/packages/effect/src/PubSub.ts +2797 -0
- package/repos/effect/packages/effect/src/Pull.ts +376 -0
- package/repos/effect/packages/effect/src/Queue.ts +1962 -0
- package/repos/effect/packages/effect/src/Random.ts +549 -0
- package/repos/effect/packages/effect/src/RcMap.ts +612 -0
- package/repos/effect/packages/effect/src/RcRef.ts +225 -0
- package/repos/effect/packages/effect/src/Record.ts +1563 -0
- package/repos/effect/packages/effect/src/Redactable.ts +168 -0
- package/repos/effect/packages/effect/src/Redacted.ts +314 -0
- package/repos/effect/packages/effect/src/Reducer.ts +178 -0
- package/repos/effect/packages/effect/src/Ref.ts +801 -0
- package/repos/effect/packages/effect/src/References.ts +786 -0
- package/repos/effect/packages/effect/src/RegExp.ts +82 -0
- package/repos/effect/packages/effect/src/Request.ts +598 -0
- package/repos/effect/packages/effect/src/RequestResolver.ts +1249 -0
- package/repos/effect/packages/effect/src/Resource.ts +184 -0
- package/repos/effect/packages/effect/src/Result.ts +1939 -0
- package/repos/effect/packages/effect/src/Runtime.ts +432 -0
- package/repos/effect/packages/effect/src/Schedule.ts +3564 -0
- package/repos/effect/packages/effect/src/Scheduler.ts +285 -0
- package/repos/effect/packages/effect/src/Schema.ts +14653 -0
- package/repos/effect/packages/effect/src/SchemaAST.ts +3903 -0
- package/repos/effect/packages/effect/src/SchemaGetter.ts +1870 -0
- package/repos/effect/packages/effect/src/SchemaIssue.ts +1176 -0
- package/repos/effect/packages/effect/src/SchemaParser.ts +1105 -0
- package/repos/effect/packages/effect/src/SchemaRepresentation.ts +3944 -0
- package/repos/effect/packages/effect/src/SchemaTransformation.ts +1818 -0
- package/repos/effect/packages/effect/src/SchemaUtils.ts +51 -0
- package/repos/effect/packages/effect/src/Scope.ts +572 -0
- package/repos/effect/packages/effect/src/ScopedCache.ts +820 -0
- package/repos/effect/packages/effect/src/ScopedRef.ts +192 -0
- package/repos/effect/packages/effect/src/Semaphore.ts +517 -0
- package/repos/effect/packages/effect/src/Sink.ts +2174 -0
- package/repos/effect/packages/effect/src/Stdio.ts +143 -0
- package/repos/effect/packages/effect/src/Stream.ts +11722 -0
- package/repos/effect/packages/effect/src/String.ts +1427 -0
- package/repos/effect/packages/effect/src/Struct.ts +979 -0
- package/repos/effect/packages/effect/src/SubscriptionRef.ts +1021 -0
- package/repos/effect/packages/effect/src/Symbol.ts +31 -0
- package/repos/effect/packages/effect/src/SynchronizedRef.ts +668 -0
- package/repos/effect/packages/effect/src/Take.ts +46 -0
- package/repos/effect/packages/effect/src/Terminal.ts +188 -0
- package/repos/effect/packages/effect/src/Tracer.ts +683 -0
- package/repos/effect/packages/effect/src/Trie.ts +953 -0
- package/repos/effect/packages/effect/src/Tuple.ts +737 -0
- package/repos/effect/packages/effect/src/TxChunk.ts +822 -0
- package/repos/effect/packages/effect/src/TxDeferred.ts +319 -0
- package/repos/effect/packages/effect/src/TxHashMap.ts +2165 -0
- package/repos/effect/packages/effect/src/TxHashSet.ts +908 -0
- package/repos/effect/packages/effect/src/TxPriorityQueue.ts +567 -0
- package/repos/effect/packages/effect/src/TxPubSub.ts +684 -0
- package/repos/effect/packages/effect/src/TxQueue.ts +1488 -0
- package/repos/effect/packages/effect/src/TxReentrantLock.ts +655 -0
- package/repos/effect/packages/effect/src/TxRef.ts +282 -0
- package/repos/effect/packages/effect/src/TxSemaphore.ts +707 -0
- package/repos/effect/packages/effect/src/TxSubscriptionRef.ts +518 -0
- package/repos/effect/packages/effect/src/Types.ts +1121 -0
- package/repos/effect/packages/effect/src/UndefinedOr.ts +239 -0
- package/repos/effect/packages/effect/src/Unify.ts +314 -0
- package/repos/effect/packages/effect/src/Utils.ts +221 -0
- package/repos/effect/packages/effect/src/index.ts +712 -0
- package/repos/effect/packages/effect/src/internal/array.ts +8 -0
- package/repos/effect/packages/effect/src/internal/concurrency.ts +52 -0
- package/repos/effect/packages/effect/src/internal/core.ts +666 -0
- package/repos/effect/packages/effect/src/internal/dateTime.ts +1264 -0
- package/repos/effect/packages/effect/src/internal/doNotation.ts +117 -0
- package/repos/effect/packages/effect/src/internal/effect.ts +6427 -0
- package/repos/effect/packages/effect/src/internal/equal.ts +28 -0
- package/repos/effect/packages/effect/src/internal/errors.ts +9 -0
- package/repos/effect/packages/effect/src/internal/executionPlan.ts +120 -0
- package/repos/effect/packages/effect/src/internal/hashMap.ts +1309 -0
- package/repos/effect/packages/effect/src/internal/hashSet.ts +190 -0
- package/repos/effect/packages/effect/src/internal/layer.ts +88 -0
- package/repos/effect/packages/effect/src/internal/matcher.ts +637 -0
- package/repos/effect/packages/effect/src/internal/metric.ts +2 -0
- package/repos/effect/packages/effect/src/internal/option.ts +98 -0
- package/repos/effect/packages/effect/src/internal/random.ts +20 -0
- package/repos/effect/packages/effect/src/internal/rcRef.ts +189 -0
- package/repos/effect/packages/effect/src/internal/record.ts +18 -0
- package/repos/effect/packages/effect/src/internal/redacted.ts +19 -0
- package/repos/effect/packages/effect/src/internal/references.ts +72 -0
- package/repos/effect/packages/effect/src/internal/request.ts +205 -0
- package/repos/effect/packages/effect/src/internal/result.ts +112 -0
- package/repos/effect/packages/effect/src/internal/schedule.ts +248 -0
- package/repos/effect/packages/effect/src/internal/schema/annotations.ts +37 -0
- package/repos/effect/packages/effect/src/internal/schema/arbitrary.ts +894 -0
- package/repos/effect/packages/effect/src/internal/schema/cause.ts +26 -0
- package/repos/effect/packages/effect/src/internal/schema/equivalence.ts +154 -0
- package/repos/effect/packages/effect/src/internal/schema/representation.ts +799 -0
- package/repos/effect/packages/effect/src/internal/schema/schema.ts +128 -0
- package/repos/effect/packages/effect/src/internal/stream.ts +28 -0
- package/repos/effect/packages/effect/src/internal/tracer.ts +41 -0
- package/repos/effect/packages/effect/src/internal/trie.ts +733 -0
- package/repos/effect/packages/effect/src/internal/version.ts +2 -0
- package/repos/effect/packages/effect/src/testing/FastCheck.ts +89 -0
- package/repos/effect/packages/effect/src/testing/TestClock.ts +547 -0
- package/repos/effect/packages/effect/src/testing/TestConsole.ts +369 -0
- package/repos/effect/packages/effect/src/testing/TestSchema.ts +567 -0
- package/repos/effect/packages/effect/src/testing/index.ts +25 -0
- package/repos/effect/packages/effect/src/unstable/ai/AiError.ts +1629 -0
- package/repos/effect/packages/effect/src/unstable/ai/AnthropicStructuredOutput.ts +407 -0
- package/repos/effect/packages/effect/src/unstable/ai/Chat.ts +931 -0
- package/repos/effect/packages/effect/src/unstable/ai/EmbeddingModel.ts +269 -0
- package/repos/effect/packages/effect/src/unstable/ai/IdGenerator.ts +300 -0
- package/repos/effect/packages/effect/src/unstable/ai/LanguageModel.ts +2221 -0
- package/repos/effect/packages/effect/src/unstable/ai/McpSchema.ts +2527 -0
- package/repos/effect/packages/effect/src/unstable/ai/McpServer.ts +1468 -0
- package/repos/effect/packages/effect/src/unstable/ai/Model.ts +166 -0
- package/repos/effect/packages/effect/src/unstable/ai/OpenAiStructuredOutput.ts +476 -0
- package/repos/effect/packages/effect/src/unstable/ai/Prompt.ts +2234 -0
- package/repos/effect/packages/effect/src/unstable/ai/Response.ts +2582 -0
- package/repos/effect/packages/effect/src/unstable/ai/ResponseIdTracker.ts +139 -0
- package/repos/effect/packages/effect/src/unstable/ai/Telemetry.ts +515 -0
- package/repos/effect/packages/effect/src/unstable/ai/Tokenizer.ts +176 -0
- package/repos/effect/packages/effect/src/unstable/ai/Tool.ts +2003 -0
- package/repos/effect/packages/effect/src/unstable/ai/Toolkit.ts +554 -0
- package/repos/effect/packages/effect/src/unstable/ai/index.ts +90 -0
- package/repos/effect/packages/effect/src/unstable/ai/internal/codec-transformer.ts +13 -0
- package/repos/effect/packages/effect/src/unstable/cli/Argument.ts +749 -0
- package/repos/effect/packages/effect/src/unstable/cli/CliError.ts +549 -0
- package/repos/effect/packages/effect/src/unstable/cli/CliOutput.ts +607 -0
- package/repos/effect/packages/effect/src/unstable/cli/Command.ts +1610 -0
- package/repos/effect/packages/effect/src/unstable/cli/Completions.ts +123 -0
- package/repos/effect/packages/effect/src/unstable/cli/Flag.ts +986 -0
- package/repos/effect/packages/effect/src/unstable/cli/GlobalFlag.ts +295 -0
- package/repos/effect/packages/effect/src/unstable/cli/HelpDoc.ts +323 -0
- package/repos/effect/packages/effect/src/unstable/cli/Param.ts +2193 -0
- package/repos/effect/packages/effect/src/unstable/cli/Primitive.ts +766 -0
- package/repos/effect/packages/effect/src/unstable/cli/Prompt.ts +3852 -0
- package/repos/effect/packages/effect/src/unstable/cli/SEMANTICS.md +157 -0
- package/repos/effect/packages/effect/src/unstable/cli/index.ts +60 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/ansi.ts +152 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/auto-suggest.ts +41 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/command.ts +340 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/bash.ts +222 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/descriptor.ts +133 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/fish.ts +253 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/zsh.ts +220 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/config.ts +272 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/help.ts +181 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/lexer.ts +70 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/parser.ts +932 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterCron.ts +163 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterError.ts +238 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterMetrics.ts +112 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterSchema.ts +170 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterWorkflowEngine.ts +778 -0
- package/repos/effect/packages/effect/src/unstable/cluster/DeliverAt.ts +58 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Entity.ts +779 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityAddress.ts +93 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityId.ts +50 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityProxy.ts +263 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityProxyServer.ts +149 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityResource.ts +184 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityType.ts +52 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Envelope.ts +433 -0
- package/repos/effect/packages/effect/src/unstable/cluster/HttpRunner.ts +345 -0
- package/repos/effect/packages/effect/src/unstable/cluster/K8sHttpClient.ts +297 -0
- package/repos/effect/packages/effect/src/unstable/cluster/MachineId.ts +54 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Message.ts +314 -0
- package/repos/effect/packages/effect/src/unstable/cluster/MessageStorage.ts +1072 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Reply.ts +455 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Runner.ts +129 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerAddress.ts +112 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerHealth.ts +145 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerServer.ts +220 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerStorage.ts +243 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Runners.ts +690 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ShardId.ts +178 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Sharding.ts +1488 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ShardingConfig.ts +367 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ShardingRegistrationEvent.ts +76 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SingleRunner.ts +75 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Singleton.ts +56 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SingletonAddress.ts +49 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Snowflake.ts +282 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SocketRunner.ts +96 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SqlMessageStorage.ts +1045 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SqlRunnerStorage.ts +700 -0
- package/repos/effect/packages/effect/src/unstable/cluster/TestRunner.ts +36 -0
- package/repos/effect/packages/effect/src/unstable/cluster/index.ts +195 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/entityManager.ts +678 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/entityReaper.ts +58 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/hash.ts +23 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/interruptors.ts +2 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/resourceMap.ts +100 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/resourceRef.ts +99 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevTools.ts +68 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevToolsClient.ts +236 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevToolsSchema.ts +558 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevToolsServer.ts +94 -0
- package/repos/effect/packages/effect/src/unstable/devtools/index.ts +25 -0
- package/repos/effect/packages/effect/src/unstable/encoding/Msgpack.ts +383 -0
- package/repos/effect/packages/effect/src/unstable/encoding/Ndjson.ts +602 -0
- package/repos/effect/packages/effect/src/unstable/encoding/Sse.ts +593 -0
- package/repos/effect/packages/effect/src/unstable/encoding/index.ts +20 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/Event.ts +447 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventGroup.ts +193 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventJournal.ts +795 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLog.ts +1030 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogEncryption.ts +169 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogMessage.ts +354 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogRemote.ts +377 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogServer.ts +242 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogServerEncrypted.ts +268 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogServerUnencrypted.ts +898 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogSessionAuth.ts +524 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/SqlEventJournal.ts +353 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/SqlEventLogServerEncrypted.ts +343 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +527 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/index.ts +75 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/internal/identityRootSecretDerivation.ts +153 -0
- package/repos/effect/packages/effect/src/unstable/http/Cookies.ts +952 -0
- package/repos/effect/packages/effect/src/unstable/http/Etag.ts +141 -0
- package/repos/effect/packages/effect/src/unstable/http/FetchHttpClient.ts +123 -0
- package/repos/effect/packages/effect/src/unstable/http/FindMyWay.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/http/Headers.ts +438 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpBody.ts +545 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClient.ts +1630 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClientError.ts +328 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClientRequest.ts +968 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClientResponse.ts +408 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpEffect.ts +400 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpIncomingMessage.ts +153 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpMethod.ts +124 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpMiddleware.ts +394 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpPlatform.ts +165 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpRouter.ts +1341 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServer.ts +329 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerError.ts +374 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerRequest.ts +1081 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerRespondable.ts +115 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerResponse.ts +1381 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpStaticServer.ts +464 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpTraceContext.ts +160 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipart.ts +830 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/HeadersParser.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/Node.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/Search.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/Web.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/http/Template.ts +262 -0
- package/repos/effect/packages/effect/src/unstable/http/Url.ts +330 -0
- package/repos/effect/packages/effect/src/unstable/http/UrlParams.ts +678 -0
- package/repos/effect/packages/effect/src/unstable/http/index.ts +145 -0
- package/repos/effect/packages/effect/src/unstable/http/internal/preResponseHandler.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApi.ts +316 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiBuilder.ts +1015 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiClient.ts +1005 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiEndpoint.ts +1545 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiError.ts +443 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiGroup.ts +381 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiMiddleware.ts +478 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiScalar.ts +267 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiSchema.ts +733 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiSecurity.ts +244 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiSwagger.ts +68 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiTest.ts +112 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/OpenApi.ts +1098 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/index.ts +70 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/internal/html.ts +18 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/internal/httpApiScalar.ts +5 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/internal/httpApiSwagger.ts +9 -0
- package/repos/effect/packages/effect/src/unstable/observability/Otlp.ts +172 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpExporter.ts +149 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpLogger.ts +340 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpMetrics.ts +826 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpResource.ts +288 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpSerialization.ts +66 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpTracer.ts +442 -0
- package/repos/effect/packages/effect/src/unstable/observability/PrometheusMetrics.ts +468 -0
- package/repos/effect/packages/effect/src/unstable/observability/index.ts +45 -0
- package/repos/effect/packages/effect/src/unstable/observability/internal/otlpEnv.ts +39 -0
- package/repos/effect/packages/effect/src/unstable/observability/internal/otlpProtobuf.ts +779 -0
- package/repos/effect/packages/effect/src/unstable/observability/internal/protobuf.ts +262 -0
- package/repos/effect/packages/effect/src/unstable/persistence/KeyValueStore.ts +864 -0
- package/repos/effect/packages/effect/src/unstable/persistence/Persistable.ts +252 -0
- package/repos/effect/packages/effect/src/unstable/persistence/PersistedCache.ts +111 -0
- package/repos/effect/packages/effect/src/unstable/persistence/PersistedQueue.ts +1196 -0
- package/repos/effect/packages/effect/src/unstable/persistence/Persistence.ts +1071 -0
- package/repos/effect/packages/effect/src/unstable/persistence/RateLimiter.ts +748 -0
- package/repos/effect/packages/effect/src/unstable/persistence/Redis.ts +188 -0
- package/repos/effect/packages/effect/src/unstable/persistence/index.ts +40 -0
- package/repos/effect/packages/effect/src/unstable/process/ChildProcess.ts +1036 -0
- package/repos/effect/packages/effect/src/unstable/process/ChildProcessSpawner.ts +285 -0
- package/repos/effect/packages/effect/src/unstable/process/index.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AsyncResult.ts +1081 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/Atom.ts +2520 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomHttpApi.ts +352 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomRef.ts +352 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomRegistry.ts +1127 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomRpc.ts +305 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/Hydration.ts +155 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/Reactivity.ts +348 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/index.ts +45 -0
- package/repos/effect/packages/effect/src/unstable/rpc/Rpc.ts +1255 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcClient.ts +1370 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcClientError.ts +57 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcGroup.ts +409 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcMessage.ts +402 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcMiddleware.ts +344 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcSchema.ts +97 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcSerialization.ts +546 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcServer.ts +1492 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcTest.ts +56 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcWorker.ts +118 -0
- package/repos/effect/packages/effect/src/unstable/rpc/Utils.ts +120 -0
- package/repos/effect/packages/effect/src/unstable/rpc/index.ts +65 -0
- package/repos/effect/packages/effect/src/unstable/schema/Model.ts +862 -0
- package/repos/effect/packages/effect/src/unstable/schema/VariantSchema.ts +604 -0
- package/repos/effect/packages/effect/src/unstable/schema/index.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/socket/Socket.ts +911 -0
- package/repos/effect/packages/effect/src/unstable/socket/SocketServer.ts +147 -0
- package/repos/effect/packages/effect/src/unstable/socket/index.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/sql/Migrator.ts +440 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlClient.ts +342 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlConnection.ts +83 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlError.ts +590 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlModel.ts +359 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlResolver.ts +380 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlSchema.ts +172 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlStream.ts +81 -0
- package/repos/effect/packages/effect/src/unstable/sql/Statement.ts +1500 -0
- package/repos/effect/packages/effect/src/unstable/sql/index.ts +50 -0
- package/repos/effect/packages/effect/src/unstable/workers/Transferable.ts +191 -0
- package/repos/effect/packages/effect/src/unstable/workers/Worker.ts +245 -0
- package/repos/effect/packages/effect/src/unstable/workers/WorkerError.ts +148 -0
- package/repos/effect/packages/effect/src/unstable/workers/WorkerRunner.ts +57 -0
- package/repos/effect/packages/effect/src/unstable/workers/index.ts +25 -0
- package/repos/effect/packages/effect/src/unstable/workflow/Activity.ts +322 -0
- package/repos/effect/packages/effect/src/unstable/workflow/DurableClock.ts +117 -0
- package/repos/effect/packages/effect/src/unstable/workflow/DurableDeferred.ts +653 -0
- package/repos/effect/packages/effect/src/unstable/workflow/DurableQueue.ts +360 -0
- package/repos/effect/packages/effect/src/unstable/workflow/Workflow.ts +898 -0
- package/repos/effect/packages/effect/src/unstable/workflow/WorkflowEngine.ts +759 -0
- package/repos/effect/packages/effect/src/unstable/workflow/WorkflowProxy.ts +212 -0
- package/repos/effect/packages/effect/src/unstable/workflow/WorkflowProxyServer.ts +151 -0
- package/repos/effect/packages/effect/src/unstable/workflow/index.ts +45 -0
- package/repos/effect/packages/effect/src/unstable/workflow/internal/crypto.ts +15 -0
- package/repos/effect/packages/effect/test/Array.test.ts +1579 -0
- package/repos/effect/packages/effect/test/AtomRef.test.ts +27 -0
- package/repos/effect/packages/effect/test/BigDecimal.test.ts +525 -0
- package/repos/effect/packages/effect/test/BigInt.test.ts +57 -0
- package/repos/effect/packages/effect/test/Boolean.test.ts +289 -0
- package/repos/effect/packages/effect/test/Brand.test.ts +160 -0
- package/repos/effect/packages/effect/test/Cache.test.ts +1423 -0
- package/repos/effect/packages/effect/test/Cause.test.ts +834 -0
- package/repos/effect/packages/effect/test/Channel.test.ts +556 -0
- package/repos/effect/packages/effect/test/Chunk.test.ts +874 -0
- package/repos/effect/packages/effect/test/Combiner.test.ts +42 -0
- package/repos/effect/packages/effect/test/Config.test.ts +1416 -0
- package/repos/effect/packages/effect/test/ConfigProvider.test.ts +726 -0
- package/repos/effect/packages/effect/test/Cron.test.ts +401 -0
- package/repos/effect/packages/effect/test/Crypto.test.ts +86 -0
- package/repos/effect/packages/effect/test/Data.test.ts +269 -0
- package/repos/effect/packages/effect/test/DateTime.test.ts +953 -0
- package/repos/effect/packages/effect/test/Deferred.test.ts +165 -0
- package/repos/effect/packages/effect/test/Duration.test.ts +679 -0
- package/repos/effect/packages/effect/test/Effect.test.ts +2658 -0
- package/repos/effect/packages/effect/test/EffectEager.test.ts +678 -0
- package/repos/effect/packages/effect/test/EffectKeepAlive.test.ts +71 -0
- package/repos/effect/packages/effect/test/Equal.test.ts +1278 -0
- package/repos/effect/packages/effect/test/Equivalence.test.ts +170 -0
- package/repos/effect/packages/effect/test/ExecutionPlan.test.ts +117 -0
- package/repos/effect/packages/effect/test/Exit.test.ts +12 -0
- package/repos/effect/packages/effect/test/Fiber.test.ts +9 -0
- package/repos/effect/packages/effect/test/FiberHandle.test.ts +146 -0
- package/repos/effect/packages/effect/test/FiberMap.test.ts +171 -0
- package/repos/effect/packages/effect/test/FiberSet.test.ts +119 -0
- package/repos/effect/packages/effect/test/Formatter.test.ts +247 -0
- package/repos/effect/packages/effect/test/Function.test.ts +333 -0
- package/repos/effect/packages/effect/test/Graph.test.ts +3505 -0
- package/repos/effect/packages/effect/test/HashMap.test.ts +618 -0
- package/repos/effect/packages/effect/test/HashSet.test.ts +298 -0
- package/repos/effect/packages/effect/test/HttpClient.test.ts +131 -0
- package/repos/effect/packages/effect/test/Iterable.test.ts +486 -0
- package/repos/effect/packages/effect/test/JsonPatch.test.ts +948 -0
- package/repos/effect/packages/effect/test/JsonPointer.test.ts +353 -0
- package/repos/effect/packages/effect/test/JsonSchema.test.ts +1253 -0
- package/repos/effect/packages/effect/test/Latch.test.ts +21 -0
- package/repos/effect/packages/effect/test/Layer.test.ts +648 -0
- package/repos/effect/packages/effect/test/LayerMap.test.ts +98 -0
- package/repos/effect/packages/effect/test/LogLevel.test.ts +28 -0
- package/repos/effect/packages/effect/test/Logger.test.ts +154 -0
- package/repos/effect/packages/effect/test/ManagedRuntime.test.ts +58 -0
- package/repos/effect/packages/effect/test/Match.test.ts +27 -0
- package/repos/effect/packages/effect/test/Metric.test.ts +682 -0
- package/repos/effect/packages/effect/test/Migrator.test.ts +69 -0
- package/repos/effect/packages/effect/test/MutableHashMap.test.ts +309 -0
- package/repos/effect/packages/effect/test/MutableHashSet.test.ts +10 -0
- package/repos/effect/packages/effect/test/MutableList.test.ts +58 -0
- package/repos/effect/packages/effect/test/Newtype.test.ts +90 -0
- package/repos/effect/packages/effect/test/Number.test.ts +422 -0
- package/repos/effect/packages/effect/test/Optic.test.ts +452 -0
- package/repos/effect/packages/effect/test/Option.test.ts +564 -0
- package/repos/effect/packages/effect/test/Order.test.ts +163 -0
- package/repos/effect/packages/effect/test/Ordering.test.ts +18 -0
- package/repos/effect/packages/effect/test/PartitionedSemaphore.test.ts +74 -0
- package/repos/effect/packages/effect/test/Pathfinding.test.ts +426 -0
- package/repos/effect/packages/effect/test/Pool.test.ts +422 -0
- package/repos/effect/packages/effect/test/Predicate.test.ts +555 -0
- package/repos/effect/packages/effect/test/PubSub.test.ts +538 -0
- package/repos/effect/packages/effect/test/Queue.test.ts +317 -0
- package/repos/effect/packages/effect/test/Random.test.ts +238 -0
- package/repos/effect/packages/effect/test/RcMap.test.ts +237 -0
- package/repos/effect/packages/effect/test/RcRef.test.ts +97 -0
- package/repos/effect/packages/effect/test/Record.test.ts +395 -0
- package/repos/effect/packages/effect/test/Redacted.test.ts +59 -0
- package/repos/effect/packages/effect/test/Reducer.test.ts +12 -0
- package/repos/effect/packages/effect/test/Ref.test.ts +187 -0
- package/repos/effect/packages/effect/test/Request.test.ts +305 -0
- package/repos/effect/packages/effect/test/Resource.test.ts +59 -0
- package/repos/effect/packages/effect/test/Result.test.ts +517 -0
- package/repos/effect/packages/effect/test/Schedule.test.ts +395 -0
- package/repos/effect/packages/effect/test/Scheduler.test.ts +70 -0
- package/repos/effect/packages/effect/test/Scope.test.ts +19 -0
- package/repos/effect/packages/effect/test/ScopedCache.test.ts +2316 -0
- package/repos/effect/packages/effect/test/ScopedRef.test.ts +80 -0
- package/repos/effect/packages/effect/test/Semaphore.test.ts +469 -0
- package/repos/effect/packages/effect/test/Sink.test.ts +230 -0
- package/repos/effect/packages/effect/test/Stream.test.ts +4712 -0
- package/repos/effect/packages/effect/test/String.test.ts +690 -0
- package/repos/effect/packages/effect/test/Struct.test.ts +216 -0
- package/repos/effect/packages/effect/test/SubscriptionRef.test.ts +90 -0
- package/repos/effect/packages/effect/test/Symbol.test.ts +50 -0
- package/repos/effect/packages/effect/test/SynchronizedRef.test.ts +105 -0
- package/repos/effect/packages/effect/test/TestClock.test.ts +71 -0
- package/repos/effect/packages/effect/test/Tracer.test.ts +410 -0
- package/repos/effect/packages/effect/test/Trie.test.ts +531 -0
- package/repos/effect/packages/effect/test/Tuple.test.ts +127 -0
- package/repos/effect/packages/effect/test/TxChunk.test.ts +342 -0
- package/repos/effect/packages/effect/test/TxDeferred.test.ts +197 -0
- package/repos/effect/packages/effect/test/TxHashMap.test.ts +963 -0
- package/repos/effect/packages/effect/test/TxHashSet.test.ts +442 -0
- package/repos/effect/packages/effect/test/TxPriorityQueue.test.ts +187 -0
- package/repos/effect/packages/effect/test/TxPubSub.test.ts +391 -0
- package/repos/effect/packages/effect/test/TxQueue.test.ts +1260 -0
- package/repos/effect/packages/effect/test/TxReentrantLock.test.ts +413 -0
- package/repos/effect/packages/effect/test/TxSemaphore.test.ts +283 -0
- package/repos/effect/packages/effect/test/TxSubscriptionRef.test.ts +197 -0
- package/repos/effect/packages/effect/test/UndefinedOr.test.ts +65 -0
- package/repos/effect/packages/effect/test/cluster/ClusterWorkflowEngine.test.ts +652 -0
- package/repos/effect/packages/effect/test/cluster/Entity.test.ts +81 -0
- package/repos/effect/packages/effect/test/cluster/K8sHttpClient.test.ts +34 -0
- package/repos/effect/packages/effect/test/cluster/MessageStorage.test.ts +196 -0
- package/repos/effect/packages/effect/test/cluster/Sharding.test.ts +578 -0
- package/repos/effect/packages/effect/test/cluster/TestEntity.ts +132 -0
- package/repos/effect/packages/effect/test/reactivity/AsyncResult.test.ts +41 -0
- package/repos/effect/packages/effect/test/reactivity/Atom.test.ts +2551 -0
- package/repos/effect/packages/effect/test/reactivity/AtomHttpApi.test.ts +86 -0
- package/repos/effect/packages/effect/test/reactivity/AtomRpc.test.ts +70 -0
- package/repos/effect/packages/effect/test/rpc/Rpc.test.ts +73 -0
- package/repos/effect/packages/effect/test/rpc/RpcClient.test.ts +58 -0
- package/repos/effect/packages/effect/test/rpc/RpcSerialization.test.ts +171 -0
- package/repos/effect/packages/effect/test/schema/HMR.test.ts +72 -0
- package/repos/effect/packages/effect/test/schema/Schema.test.ts +9133 -0
- package/repos/effect/packages/effect/test/schema/SchemaAST.test.ts +280 -0
- package/repos/effect/packages/effect/test/schema/SchemaGetter.test.ts +383 -0
- package/repos/effect/packages/effect/test/schema/SchemaIssue.test.ts +9 -0
- package/repos/effect/packages/effect/test/schema/SchemaParser.test.ts +323 -0
- package/repos/effect/packages/effect/test/schema/fixtures/HMR-Class.ts +5 -0
- package/repos/effect/packages/effect/test/schema/fixtures/HMR-sanity-check.ts +3 -0
- package/repos/effect/packages/effect/test/schema/representation/fromASTs.test.ts +820 -0
- package/repos/effect/packages/effect/test/schema/representation/fromJsonSchemaDocument.test.ts +2137 -0
- package/repos/effect/packages/effect/test/schema/representation/toCodeDocument.test.ts +2089 -0
- package/repos/effect/packages/effect/test/schema/representation/toJsonSchemaMultiDocument.test.ts +39 -0
- package/repos/effect/packages/effect/test/schema/representation/toSchema.test.ts +506 -0
- package/repos/effect/packages/effect/test/schema/toArbitrary.test.ts +1693 -0
- package/repos/effect/packages/effect/test/schema/toCodec.test.ts +3149 -0
- package/repos/effect/packages/effect/test/schema/toDifferJsonPatch.test.ts +239 -0
- package/repos/effect/packages/effect/test/schema/toEquivalence.test.ts +519 -0
- package/repos/effect/packages/effect/test/schema/toFormatter.test.ts +565 -0
- package/repos/effect/packages/effect/test/schema/toIso.test.ts +394 -0
- package/repos/effect/packages/effect/test/schema/toJsonSchemaDocument.test.ts +3630 -0
- package/repos/effect/packages/effect/test/schema/toStandardJSONSchemaV1.test.ts +126 -0
- package/repos/effect/packages/effect/test/schema/toStandardSchemaV1.test.ts +495 -0
- package/repos/effect/packages/effect/test/schema/v3-v4.test.ts +250 -0
- package/repos/effect/packages/effect/test/testing/TestSchema.test.ts +78 -0
- package/repos/effect/packages/effect/test/unstable/ai/AiError.test.ts +823 -0
- package/repos/effect/packages/effect/test/unstable/ai/AnthropicStructuredOutput.test.ts +593 -0
- package/repos/effect/packages/effect/test/unstable/ai/Chat.test.ts +147 -0
- package/repos/effect/packages/effect/test/unstable/ai/EmbeddingModel.test.ts +185 -0
- package/repos/effect/packages/effect/test/unstable/ai/LanguageModel.test.ts +1714 -0
- package/repos/effect/packages/effect/test/unstable/ai/LanguageModelTrackerLifecycle.test.ts +413 -0
- package/repos/effect/packages/effect/test/unstable/ai/McpServer.test.ts +82 -0
- package/repos/effect/packages/effect/test/unstable/ai/Model.test.ts +16 -0
- package/repos/effect/packages/effect/test/unstable/ai/OpenAiStructuredOutput.test.ts +723 -0
- package/repos/effect/packages/effect/test/unstable/ai/Prompt.test.ts +346 -0
- package/repos/effect/packages/effect/test/unstable/ai/ResponseIdTracker.test.ts +424 -0
- package/repos/effect/packages/effect/test/unstable/ai/Tool.test.ts +1264 -0
- package/repos/effect/packages/effect/test/unstable/ai/utils.ts +68 -0
- package/repos/effect/packages/effect/test/unstable/cli/Arguments.test.ts +390 -0
- package/repos/effect/packages/effect/test/unstable/cli/Command.test.ts +1801 -0
- package/repos/effect/packages/effect/test/unstable/cli/Errors.test.ts +150 -0
- package/repos/effect/packages/effect/test/unstable/cli/Help.test.ts +572 -0
- package/repos/effect/packages/effect/test/unstable/cli/LogLevel.test.ts +202 -0
- package/repos/effect/packages/effect/test/unstable/cli/Param.test.ts +391 -0
- package/repos/effect/packages/effect/test/unstable/cli/Primitive.test.ts +321 -0
- package/repos/effect/packages/effect/test/unstable/cli/Prompt.test.ts +597 -0
- package/repos/effect/packages/effect/test/unstable/cli/completions/completions.test.ts +656 -0
- package/repos/effect/packages/effect/test/unstable/cli/completions/descriptor.test.ts +245 -0
- package/repos/effect/packages/effect/test/unstable/cli/fixtures/ComprehensiveCli.ts +422 -0
- package/repos/effect/packages/effect/test/unstable/cli/services/MockTerminal.ts +135 -0
- package/repos/effect/packages/effect/test/unstable/cli/services/TestActions.ts +36 -0
- package/repos/effect/packages/effect/test/unstable/encoding/Ndjson.test.ts +18 -0
- package/repos/effect/packages/effect/test/unstable/encoding/Sse.test.ts +62 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventJournal.test.ts +25 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLog.test.ts +104 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLogIdentityDerivation.test.ts +85 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLogRemote.test.ts +176 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLogSessionAuth.test.ts +130 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/SqlEventLogServerUnencryptedStorageTest.ts +169 -0
- package/repos/effect/packages/effect/test/unstable/http/Cookies.test.ts +80 -0
- package/repos/effect/packages/effect/test/unstable/http/Headers.test.ts +73 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpClient.test.ts +306 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpClientRequest.test.ts +164 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpEffect.test.ts +254 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpMiddleware.test.ts +57 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpServerError.test.ts +121 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpServerRequest.test.ts +157 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpServerResponse.test.ts +76 -0
- package/repos/effect/packages/effect/test/unstable/http/Multipart.test.ts +69 -0
- package/repos/effect/packages/effect/test/unstable/http/Url.test.ts +98 -0
- package/repos/effect/packages/effect/test/unstable/http/UrlParams.test.ts +30 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiBuilder.test.ts +186 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiClient.test.ts +446 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiEndpoint.test.ts +160 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiSchema.test.ts +108 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiSecurity.test.ts +41 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/OpenApi.test.ts +39 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpConfig.test.ts +151 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpExporter.test.ts +108 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpMetrics.test.ts +518 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpResource.test.ts +84 -0
- package/repos/effect/packages/effect/test/unstable/observability/PrometheusMetrics.test.ts +417 -0
- package/repos/effect/packages/effect/test/unstable/persistence/KeyValueStore.test.ts +164 -0
- package/repos/effect/packages/effect/test/unstable/persistence/KeyValueStoreTest.ts +85 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedCache.test.ts +4 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedCacheTest.ts +111 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedQueue.test.ts +4 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedQueueTest.ts +106 -0
- package/repos/effect/packages/effect/test/unstable/persistence/RateLimiter.test.ts +145 -0
- package/repos/effect/packages/effect/test/unstable/persistence/Redis.test.ts +43 -0
- package/repos/effect/packages/effect/test/unstable/process/ChildProcess.test.ts +352 -0
- package/repos/effect/packages/effect/test/unstable/schema/VariantSchema.test.ts +72 -0
- package/repos/effect/packages/effect/test/unstable/sql/SqlError.test.ts +228 -0
- package/repos/effect/packages/effect/test/unstable/sql/SqlSchema.test.ts +168 -0
- package/repos/effect/packages/effect/test/unstable/workers/WorkerError.test.ts +90 -0
- package/repos/effect/packages/effect/test/unstable/workflow/DurableQueue.test.ts +105 -0
- package/repos/effect/packages/effect/test/unstable/workflow/WorkflowEngine.test.ts +60 -0
- package/repos/effect/packages/effect/test/utils/assert.ts +182 -0
- package/repos/effect/packages/effect/test/utils/chunkCoordination.ts +36 -0
- package/repos/effect/packages/effect/test/utils/counter.ts +54 -0
- package/repos/effect/packages/effect/tsconfig.json +8 -0
- package/repos/effect/packages/effect/typetest/AiError.tst.ts +49 -0
- package/repos/effect/packages/effect/typetest/Array.tst.ts +1289 -0
- package/repos/effect/packages/effect/typetest/Brand.tst.ts +51 -0
- package/repos/effect/packages/effect/typetest/Channel.tst.ts +112 -0
- package/repos/effect/packages/effect/typetest/Config.tst.ts +31 -0
- package/repos/effect/packages/effect/typetest/Data.tst.ts +121 -0
- package/repos/effect/packages/effect/typetest/Effect.tst.ts +976 -0
- package/repos/effect/packages/effect/typetest/Equivalence.tst.ts +19 -0
- package/repos/effect/packages/effect/typetest/Newtype.tst.ts +72 -0
- package/repos/effect/packages/effect/typetest/Optic.tst.ts +130 -0
- package/repos/effect/packages/effect/typetest/Option.tst.ts +72 -0
- package/repos/effect/packages/effect/typetest/Order.tst.ts +19 -0
- package/repos/effect/packages/effect/typetest/Predicate.tst.ts +251 -0
- package/repos/effect/packages/effect/typetest/Result.tst.ts +353 -0
- package/repos/effect/packages/effect/typetest/Schedule.tst.ts +21 -0
- package/repos/effect/packages/effect/typetest/Stream.tst.ts +197 -0
- package/repos/effect/packages/effect/typetest/Struct.tst.ts +422 -0
- package/repos/effect/packages/effect/typetest/Tuple.tst.ts +177 -0
- package/repos/effect/packages/effect/typetest/Types.tst.ts +364 -0
- package/repos/effect/packages/effect/typetest/VariantSchema.tst.ts +76 -0
- package/repos/effect/packages/effect/typetest/schema/Array.tst.ts +46 -0
- package/repos/effect/packages/effect/typetest/schema/Literals.tst.ts +58 -0
- package/repos/effect/packages/effect/typetest/schema/Record.tst.ts +145 -0
- package/repos/effect/packages/effect/typetest/schema/Schema.tst.ts +1854 -0
- package/repos/effect/packages/effect/typetest/schema/Struct.tst.ts +745 -0
- package/repos/effect/packages/effect/typetest/schema/Tuple.tst.ts +199 -0
- package/repos/effect/packages/effect/typetest/schema/Union.tst.ts +198 -0
- package/repos/effect/packages/effect/typetest/schema/api.tst.ts +276 -0
- package/repos/effect/packages/effect/typetest/schema/toArbitrary.tst.ts +65 -0
- package/repos/effect/packages/effect/typetest/schema/toIso.tst.ts +282 -0
- package/repos/effect/packages/effect/typetest/unstable/ai/LanguageModel.tst.ts +191 -0
- package/repos/effect/packages/effect/typetest/unstable/ai/Tool.tst.ts +33 -0
- package/repos/effect/packages/effect/typetest/unstable/cli/Command.tst.ts +124 -0
- package/repos/effect/packages/effect/typetest/unstable/cli/Param.tst.ts +20 -0
- package/repos/effect/packages/effect/typetest/unstable/cli/Prompt.tst.ts +97 -0
- package/repos/effect/packages/effect/typetest/unstable/encoding/Ndjson.tst.ts +24 -0
- package/repos/effect/packages/effect/typetest/unstable/http/HttpClient.tst.ts +143 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiBuilder.tst.ts +98 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiClient.tst.ts +677 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiEndpoint.tst.ts +466 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiMiddleware.tst.ts +90 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiSchema.tst.ts +135 -0
- package/repos/effect/packages/effect/typetest/unstable/reactivity/AsyncResult.tst.ts +65 -0
- package/repos/effect/packages/effect/typetest/unstable/reactivity/AtomHttpApi.tst.ts +63 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/Rpc.tst.ts +74 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/RpcGroup.tst.ts +61 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/RpcMiddleware.tst.ts +41 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/RpcServer.tst.ts +26 -0
- package/repos/effect/packages/effect/typetest/unstable/sql/SqlSchema.tst.ts +75 -0
- package/repos/effect/packages/effect/typetest/unstable/workflow/Workflow.tst.ts +16 -0
- package/repos/effect/packages/effect/vitest.config.ts +11 -0
- package/repos/effect/packages/opentelemetry/CHANGELOG.md +620 -0
- package/repos/effect/packages/opentelemetry/LICENSE +21 -0
- package/repos/effect/packages/opentelemetry/README.md +5 -0
- package/repos/effect/packages/opentelemetry/docgen.json +30 -0
- package/repos/effect/packages/opentelemetry/package.json +126 -0
- package/repos/effect/packages/opentelemetry/src/Logger.ts +193 -0
- package/repos/effect/packages/opentelemetry/src/Metrics.ts +138 -0
- package/repos/effect/packages/opentelemetry/src/NodeSdk.ts +162 -0
- package/repos/effect/packages/opentelemetry/src/Resource.ts +147 -0
- package/repos/effect/packages/opentelemetry/src/Tracer.ts +594 -0
- package/repos/effect/packages/opentelemetry/src/WebSdk.ts +140 -0
- package/repos/effect/packages/opentelemetry/src/index.ts +35 -0
- package/repos/effect/packages/opentelemetry/src/internal/attributes.ts +28 -0
- package/repos/effect/packages/opentelemetry/src/internal/metrics.ts +463 -0
- package/repos/effect/packages/opentelemetry/src/internal/utilities.ts +5 -0
- package/repos/effect/packages/opentelemetry/test/Logger.test.ts +122 -0
- package/repos/effect/packages/opentelemetry/test/Metrics.test.ts +339 -0
- package/repos/effect/packages/opentelemetry/test/Tracer.test.ts +167 -0
- package/repos/effect/packages/opentelemetry/tsconfig.json +8 -0
- package/repos/effect/packages/opentelemetry/vitest.config.ts +6 -0
- package/repos/effect/packages/platform-browser/CHANGELOG.md +637 -0
- package/repos/effect/packages/platform-browser/LICENSE +21 -0
- package/repos/effect/packages/platform-browser/README.md +1 -0
- package/repos/effect/packages/platform-browser/docgen.json +21 -0
- package/repos/effect/packages/platform-browser/package.json +74 -0
- package/repos/effect/packages/platform-browser/src/BrowserCrypto.ts +97 -0
- package/repos/effect/packages/platform-browser/src/BrowserHttpClient.ts +430 -0
- package/repos/effect/packages/platform-browser/src/BrowserKeyValueStore.ts +177 -0
- package/repos/effect/packages/platform-browser/src/BrowserPersistence.ts +334 -0
- package/repos/effect/packages/platform-browser/src/BrowserRuntime.ts +53 -0
- package/repos/effect/packages/platform-browser/src/BrowserSocket.ts +52 -0
- package/repos/effect/packages/platform-browser/src/BrowserStream.ts +56 -0
- package/repos/effect/packages/platform-browser/src/BrowserWorker.ts +98 -0
- package/repos/effect/packages/platform-browser/src/BrowserWorkerRunner.ts +199 -0
- package/repos/effect/packages/platform-browser/src/Clipboard.ts +143 -0
- package/repos/effect/packages/platform-browser/src/Geolocation.ts +233 -0
- package/repos/effect/packages/platform-browser/src/IndexedDb.ts +113 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbDatabase.ts +648 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbQueryBuilder.ts +2032 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbTable.ts +260 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbVersion.ts +138 -0
- package/repos/effect/packages/platform-browser/src/Permissions.ts +146 -0
- package/repos/effect/packages/platform-browser/src/index.ts +90 -0
- package/repos/effect/packages/platform-browser/test/BrowserCrypto.test.ts +74 -0
- package/repos/effect/packages/platform-browser/test/BrowserHttpClient.test.ts +91 -0
- package/repos/effect/packages/platform-browser/test/BrowserKeyValueStore.test.ts +23 -0
- package/repos/effect/packages/platform-browser/test/BrowserPersistence.test.ts +209 -0
- package/repos/effect/packages/platform-browser/test/BrowserPersistencePersistedCache.test.ts +29 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbDatabase.test.ts +253 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbQueryBuilder.test.ts +1459 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbTable.test.ts +101 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbVersion.test.ts +50 -0
- package/repos/effect/packages/platform-browser/test/Permissions.test.ts +12 -0
- package/repos/effect/packages/platform-browser/test/RpcWorker.test.ts +19 -0
- package/repos/effect/packages/platform-browser/test/fixtures/rpc-e2e.ts +141 -0
- package/repos/effect/packages/platform-browser/test/fixtures/rpc-schemas.ts +157 -0
- package/repos/effect/packages/platform-browser/test/fixtures/rpc-worker.ts +12 -0
- package/repos/effect/packages/platform-browser/tsconfig.json +8 -0
- package/repos/effect/packages/platform-browser/vitest.config.ts +17 -0
- package/repos/effect/packages/platform-browser/vitest.setup.ts +5 -0
- package/repos/effect/packages/platform-bun/CHANGELOG.md +691 -0
- package/repos/effect/packages/platform-bun/LICENSE +21 -0
- package/repos/effect/packages/platform-bun/README.md +7 -0
- package/repos/effect/packages/platform-bun/docgen.json +20 -0
- package/repos/effect/packages/platform-bun/package.json +73 -0
- package/repos/effect/packages/platform-bun/src/BunChildProcessSpawner.ts +6 -0
- package/repos/effect/packages/platform-bun/src/BunClusterHttp.ts +174 -0
- package/repos/effect/packages/platform-bun/src/BunClusterSocket.ts +153 -0
- package/repos/effect/packages/platform-bun/src/BunCrypto.ts +24 -0
- package/repos/effect/packages/platform-bun/src/BunFileSystem.ts +20 -0
- package/repos/effect/packages/platform-bun/src/BunHttpClient.ts +9 -0
- package/repos/effect/packages/platform-bun/src/BunHttpPlatform.ts +50 -0
- package/repos/effect/packages/platform-bun/src/BunHttpServer.ts +600 -0
- package/repos/effect/packages/platform-bun/src/BunHttpServerRequest.ts +19 -0
- package/repos/effect/packages/platform-bun/src/BunMultipart.ts +54 -0
- package/repos/effect/packages/platform-bun/src/BunPath.ts +37 -0
- package/repos/effect/packages/platform-bun/src/BunRedis.ts +88 -0
- package/repos/effect/packages/platform-bun/src/BunRuntime.ts +52 -0
- package/repos/effect/packages/platform-bun/src/BunServices.ts +49 -0
- package/repos/effect/packages/platform-bun/src/BunSink.ts +8 -0
- package/repos/effect/packages/platform-bun/src/BunSocket.ts +54 -0
- package/repos/effect/packages/platform-bun/src/BunSocketServer.ts +8 -0
- package/repos/effect/packages/platform-bun/src/BunStdio.ts +22 -0
- package/repos/effect/packages/platform-bun/src/BunStream.ts +68 -0
- package/repos/effect/packages/platform-bun/src/BunTerminal.ts +32 -0
- package/repos/effect/packages/platform-bun/src/BunWorker.ts +92 -0
- package/repos/effect/packages/platform-bun/src/BunWorkerRunner.ts +113 -0
- package/repos/effect/packages/platform-bun/src/index.ts +115 -0
- package/repos/effect/packages/platform-bun/tsconfig.json +12 -0
- package/repos/effect/packages/platform-node/CHANGELOG.md +695 -0
- package/repos/effect/packages/platform-node/LICENSE +21 -0
- package/repos/effect/packages/platform-node/README.md +7 -0
- package/repos/effect/packages/platform-node/docgen.json +24 -0
- package/repos/effect/packages/platform-node/package.json +82 -0
- package/repos/effect/packages/platform-node/src/Mime.ts +25 -0
- package/repos/effect/packages/platform-node/src/NodeChildProcessSpawner.ts +6 -0
- package/repos/effect/packages/platform-node/src/NodeClusterHttp.ts +155 -0
- package/repos/effect/packages/platform-node/src/NodeClusterSocket.ts +176 -0
- package/repos/effect/packages/platform-node/src/NodeCrypto.ts +24 -0
- package/repos/effect/packages/platform-node/src/NodeFileSystem.ts +21 -0
- package/repos/effect/packages/platform-node/src/NodeHttpClient.ts +664 -0
- package/repos/effect/packages/platform-node/src/NodeHttpIncomingMessage.ts +141 -0
- package/repos/effect/packages/platform-node/src/NodeHttpPlatform.ts +70 -0
- package/repos/effect/packages/platform-node/src/NodeHttpServer.ts +646 -0
- package/repos/effect/packages/platform-node/src/NodeHttpServerRequest.ts +33 -0
- package/repos/effect/packages/platform-node/src/NodeMultipart.ts +183 -0
- package/repos/effect/packages/platform-node/src/NodePath.ts +40 -0
- package/repos/effect/packages/platform-node/src/NodeRedis.ts +92 -0
- package/repos/effect/packages/platform-node/src/NodeRuntime.ts +53 -0
- package/repos/effect/packages/platform-node/src/NodeServices.ts +50 -0
- package/repos/effect/packages/platform-node/src/NodeSink.ts +8 -0
- package/repos/effect/packages/platform-node/src/NodeSocket.ts +72 -0
- package/repos/effect/packages/platform-node/src/NodeSocketServer.ts +8 -0
- package/repos/effect/packages/platform-node/src/NodeStdio.ts +22 -0
- package/repos/effect/packages/platform-node/src/NodeStream.ts +8 -0
- package/repos/effect/packages/platform-node/src/NodeTerminal.ts +32 -0
- package/repos/effect/packages/platform-node/src/NodeWorker.ts +121 -0
- package/repos/effect/packages/platform-node/src/NodeWorkerRunner.ts +110 -0
- package/repos/effect/packages/platform-node/src/Undici.ts +29 -0
- package/repos/effect/packages/platform-node/src/index.ts +130 -0
- package/repos/effect/packages/platform-node/test/HttpApi.test.ts +1831 -0
- package/repos/effect/packages/platform-node/test/HttpStaticServer.test.ts +253 -0
- package/repos/effect/packages/platform-node/test/HttpStaticServerConditional.test.ts +296 -0
- package/repos/effect/packages/platform-node/test/NodeCrypto.test.ts +59 -0
- package/repos/effect/packages/platform-node/test/NodeHttpClient.test.ts +157 -0
- package/repos/effect/packages/platform-node/test/NodeHttpPlatform.test.ts +51 -0
- package/repos/effect/packages/platform-node/test/NodeHttpServer.test.ts +598 -0
- package/repos/effect/packages/platform-node/test/NodeRedis.test.ts +31 -0
- package/repos/effect/packages/platform-node/test/NodeSocket.test.ts +153 -0
- package/repos/effect/packages/platform-node/test/OpenApi.test.ts +1573 -0
- package/repos/effect/packages/platform-node/test/RpcServer.test.ts +213 -0
- package/repos/effect/packages/platform-node/test/__snapshots__/HttpApi.test.ts.snap +715 -0
- package/repos/effect/packages/platform-node/test/cluster/MessageStorageTest.ts +196 -0
- package/repos/effect/packages/platform-node/test/cluster/SocketRunner.test.ts +120 -0
- package/repos/effect/packages/platform-node/test/cluster/SqlMessageStorage.test.ts +222 -0
- package/repos/effect/packages/platform-node/test/cluster/SqlRunnerStorage.test.ts +101 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/conditional.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/custom/home.html +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/file.binx +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/guide/index.html +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/hello.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/index.html +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/range.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server-outside.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/mysql2-utils.ts +64 -0
- package/repos/effect/packages/platform-node/test/fixtures/pg-utils.ts +39 -0
- package/repos/effect/packages/platform-node/test/fixtures/rpc-e2e.ts +149 -0
- package/repos/effect/packages/platform-node/test/fixtures/rpc-schemas.ts +175 -0
- package/repos/effect/packages/platform-node/test/fixtures/text.txt +1 -0
- package/repos/effect/packages/platform-node/tsconfig.json +12 -0
- package/repos/effect/packages/platform-node/vitest.config.ts +6 -0
- package/repos/effect/packages/platform-node-shared/CHANGELOG.md +617 -0
- package/repos/effect/packages/platform-node-shared/LICENSE +21 -0
- package/repos/effect/packages/platform-node-shared/README.md +7 -0
- package/repos/effect/packages/platform-node-shared/docgen.json +38 -0
- package/repos/effect/packages/platform-node-shared/package.json +76 -0
- package/repos/effect/packages/platform-node-shared/src/NodeChildProcessSpawner.ts +713 -0
- package/repos/effect/packages/platform-node-shared/src/NodeClusterSocket.ts +70 -0
- package/repos/effect/packages/platform-node-shared/src/NodeCrypto.ts +60 -0
- package/repos/effect/packages/platform-node-shared/src/NodeFileSystem.ts +652 -0
- package/repos/effect/packages/platform-node-shared/src/NodePath.ts +80 -0
- package/repos/effect/packages/platform-node-shared/src/NodeRuntime.ts +59 -0
- package/repos/effect/packages/platform-node-shared/src/NodeSink.ts +116 -0
- package/repos/effect/packages/platform-node-shared/src/NodeSocket.ts +269 -0
- package/repos/effect/packages/platform-node-shared/src/NodeSocketServer.ts +301 -0
- package/repos/effect/packages/platform-node-shared/src/NodeStdio.ts +67 -0
- package/repos/effect/packages/platform-node-shared/src/NodeStream.ts +445 -0
- package/repos/effect/packages/platform-node-shared/src/NodeTerminal.ts +129 -0
- package/repos/effect/packages/platform-node-shared/src/index.ts +65 -0
- package/repos/effect/packages/platform-node-shared/src/internal/utils.ts +51 -0
- package/repos/effect/packages/platform-node-shared/test/NodeChildProcessSpawner.test.ts +1069 -0
- package/repos/effect/packages/platform-node-shared/test/NodeFileSystem.test.ts +214 -0
- package/repos/effect/packages/platform-node-shared/test/NodeSink.test.ts +153 -0
- package/repos/effect/packages/platform-node-shared/test/NodeStream.test.ts +173 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/bash/no-permissions.sh +3 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/bash/parent-exits-early.sh +31 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/bash/spawn-children.sh +32 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/SHOUTING +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/integer +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/nested/config +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/secret +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/helloworld.tar.gz +0 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/text.txt +1 -0
- package/repos/effect/packages/platform-node-shared/tsconfig.json +11 -0
- package/repos/effect/packages/platform-node-shared/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/clickhouse/CHANGELOG.md +681 -0
- package/repos/effect/packages/sql/clickhouse/LICENSE +21 -0
- package/repos/effect/packages/sql/clickhouse/README.md +7 -0
- package/repos/effect/packages/sql/clickhouse/docgen.json +24 -0
- package/repos/effect/packages/sql/clickhouse/package.json +72 -0
- package/repos/effect/packages/sql/clickhouse/src/ClickhouseClient.ts +546 -0
- package/repos/effect/packages/sql/clickhouse/src/ClickhouseMigrator.ts +51 -0
- package/repos/effect/packages/sql/clickhouse/src/index.ts +15 -0
- package/repos/effect/packages/sql/clickhouse/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/clickhouse/test/SqlErrorClassification.test.ts +75 -0
- package/repos/effect/packages/sql/clickhouse/tsconfig.json +12 -0
- package/repos/effect/packages/sql/clickhouse/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/d1/CHANGELOG.md +597 -0
- package/repos/effect/packages/sql/d1/LICENSE +21 -0
- package/repos/effect/packages/sql/d1/README.md +7 -0
- package/repos/effect/packages/sql/d1/docgen.json +24 -0
- package/repos/effect/packages/sql/d1/package.json +75 -0
- package/repos/effect/packages/sql/d1/src/D1Client.ts +249 -0
- package/repos/effect/packages/sql/d1/src/index.ts +10 -0
- package/repos/effect/packages/sql/d1/test/Client.test.ts +65 -0
- package/repos/effect/packages/sql/d1/test/Resolver.test.ts +176 -0
- package/repos/effect/packages/sql/d1/test/utils.ts +38 -0
- package/repos/effect/packages/sql/d1/tsconfig.json +8 -0
- package/repos/effect/packages/sql/d1/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/libsql/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/libsql/LICENSE +21 -0
- package/repos/effect/packages/sql/libsql/README.md +7 -0
- package/repos/effect/packages/sql/libsql/docgen.json +24 -0
- package/repos/effect/packages/sql/libsql/package.json +73 -0
- package/repos/effect/packages/sql/libsql/src/LibsqlClient.ts +381 -0
- package/repos/effect/packages/sql/libsql/src/LibsqlMigrator.ts +46 -0
- package/repos/effect/packages/sql/libsql/src/index.ts +15 -0
- package/repos/effect/packages/sql/libsql/test/Client.test.ts +106 -0
- package/repos/effect/packages/sql/libsql/test/Resolver.test.ts +177 -0
- package/repos/effect/packages/sql/libsql/test/util.ts +54 -0
- package/repos/effect/packages/sql/libsql/tsconfig.json +9 -0
- package/repos/effect/packages/sql/libsql/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/mssql/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/mssql/LICENSE +21 -0
- package/repos/effect/packages/sql/mssql/README.md +7 -0
- package/repos/effect/packages/sql/mssql/docgen.json +24 -0
- package/repos/effect/packages/sql/mssql/package.json +70 -0
- package/repos/effect/packages/sql/mssql/src/MssqlClient.ts +732 -0
- package/repos/effect/packages/sql/mssql/src/MssqlMigrator.ts +45 -0
- package/repos/effect/packages/sql/mssql/src/Parameter.ts +64 -0
- package/repos/effect/packages/sql/mssql/src/Procedure.ts +213 -0
- package/repos/effect/packages/sql/mssql/src/index.ts +32 -0
- package/repos/effect/packages/sql/mssql/test/Client.test.ts +91 -0
- package/repos/effect/packages/sql/mssql/test/SqlErrorClassification.test.ts +206 -0
- package/repos/effect/packages/sql/mssql/tsconfig.json +8 -0
- package/repos/effect/packages/sql/mssql/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/mysql2/CHANGELOG.md +603 -0
- package/repos/effect/packages/sql/mysql2/LICENSE +21 -0
- package/repos/effect/packages/sql/mysql2/README.md +7 -0
- package/repos/effect/packages/sql/mysql2/docgen.json +24 -0
- package/repos/effect/packages/sql/mysql2/package.json +71 -0
- package/repos/effect/packages/sql/mysql2/src/MysqlClient.ts +517 -0
- package/repos/effect/packages/sql/mysql2/src/MysqlMigrator.ts +102 -0
- package/repos/effect/packages/sql/mysql2/src/index.ts +15 -0
- package/repos/effect/packages/sql/mysql2/test/Client.test.ts +34 -0
- package/repos/effect/packages/sql/mysql2/test/KeyValueStore.test.ts +16 -0
- package/repos/effect/packages/sql/mysql2/test/Model.test.ts +227 -0
- package/repos/effect/packages/sql/mysql2/test/MysqlClient.test.ts +35 -0
- package/repos/effect/packages/sql/mysql2/test/Persistence.test.ts +22 -0
- package/repos/effect/packages/sql/mysql2/test/SqlErrorClassification.test.ts +133 -0
- package/repos/effect/packages/sql/mysql2/test/SqlEventLogServerUnencrypted.test.ts +7 -0
- package/repos/effect/packages/sql/mysql2/test/utils.ts +64 -0
- package/repos/effect/packages/sql/mysql2/tsconfig.json +9 -0
- package/repos/effect/packages/sql/mysql2/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/pg/CHANGELOG.md +3432 -0
- package/repos/effect/packages/sql/pg/LICENSE +21 -0
- package/repos/effect/packages/sql/pg/README.md +7 -0
- package/repos/effect/packages/sql/pg/docgen.json +24 -0
- package/repos/effect/packages/sql/pg/package.json +77 -0
- package/repos/effect/packages/sql/pg/src/PgClient.ts +947 -0
- package/repos/effect/packages/sql/pg/src/PgMigrator.ts +120 -0
- package/repos/effect/packages/sql/pg/src/index.ts +15 -0
- package/repos/effect/packages/sql/pg/test/Client.test.ts +373 -0
- package/repos/effect/packages/sql/pg/test/KeyValueStore.test.ts +16 -0
- package/repos/effect/packages/sql/pg/test/Persistence.test.ts +20 -0
- package/repos/effect/packages/sql/pg/test/SqlErrorClassification.test.ts +81 -0
- package/repos/effect/packages/sql/pg/test/SqlEventLogServerUnencrypted.test.ts +7 -0
- package/repos/effect/packages/sql/pg/test/TransactionAcquire.test.ts +52 -0
- package/repos/effect/packages/sql/pg/test/utils.ts +49 -0
- package/repos/effect/packages/sql/pg/tsconfig.json +9 -0
- package/repos/effect/packages/sql/pg/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/pglite/CHANGELOG.md +198 -0
- package/repos/effect/packages/sql/pglite/LICENSE +21 -0
- package/repos/effect/packages/sql/pglite/README.md +7 -0
- package/repos/effect/packages/sql/pglite/docgen.json +24 -0
- package/repos/effect/packages/sql/pglite/package.json +74 -0
- package/repos/effect/packages/sql/pglite/src/PgliteClient.ts +503 -0
- package/repos/effect/packages/sql/pglite/src/PgliteMigrator.ts +44 -0
- package/repos/effect/packages/sql/pglite/src/index.ts +15 -0
- package/repos/effect/packages/sql/pglite/test/Client.test.ts +149 -0
- package/repos/effect/packages/sql/pglite/test/Migrator.test.ts +45 -0
- package/repos/effect/packages/sql/pglite/test/SqlErrorClassification.test.ts +56 -0
- package/repos/effect/packages/sql/pglite/test/Transaction.test.ts +62 -0
- package/repos/effect/packages/sql/pglite/tsconfig.json +8 -0
- package/repos/effect/packages/sql/pglite/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-bun/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-bun/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-bun/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-bun/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-bun/package.json +69 -0
- package/repos/effect/packages/sql/sqlite-bun/src/SqliteClient.ts +262 -0
- package/repos/effect/packages/sql/sqlite-bun/src/SqliteMigrator.ts +90 -0
- package/repos/effect/packages/sql/sqlite-bun/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-bun/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/sqlite-bun/tsconfig.json +11 -0
- package/repos/effect/packages/sql/sqlite-bun/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-do/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-do/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-do/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-do/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-do/package.json +68 -0
- package/repos/effect/packages/sql/sqlite-do/src/SqliteClient.ts +249 -0
- package/repos/effect/packages/sql/sqlite-do/src/SqliteMigrator.ts +45 -0
- package/repos/effect/packages/sql/sqlite-do/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-do/test/Client.test.ts +24 -0
- package/repos/effect/packages/sql/sqlite-do/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-do/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-node/CHANGELOG.md +3415 -0
- package/repos/effect/packages/sql/sqlite-node/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-node/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-node/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-node/package.json +72 -0
- package/repos/effect/packages/sql/sqlite-node/src/SqliteClient.ts +312 -0
- package/repos/effect/packages/sql/sqlite-node/src/SqliteMigrator.ts +90 -0
- package/repos/effect/packages/sql/sqlite-node/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-node/test/Client.test.ts +75 -0
- package/repos/effect/packages/sql/sqlite-node/test/KeyValueStore.test.ts +29 -0
- package/repos/effect/packages/sql/sqlite-node/test/Persistence.test.ts +109 -0
- package/repos/effect/packages/sql/sqlite-node/test/Resolver.test.ts +183 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqlEventJournal.test.ts +84 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqlEventLogServerEncrypted.test.ts +249 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqlEventLogServerUnencrypted.test.ts +110 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqliteMigrator.test.ts +48 -0
- package/repos/effect/packages/sql/sqlite-node/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-node/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-react-native/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-react-native/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-react-native/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-react-native/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-react-native/package.json +69 -0
- package/repos/effect/packages/sql/sqlite-react-native/src/SqliteClient.ts +354 -0
- package/repos/effect/packages/sql/sqlite-react-native/src/SqliteMigrator.ts +55 -0
- package/repos/effect/packages/sql/sqlite-react-native/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-react-native/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/sqlite-react-native/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-react-native/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-wasm/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-wasm/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-wasm/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-wasm/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-wasm/package.json +69 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/OpfsWorker.ts +118 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/SqliteClient.ts +551 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/SqliteMigrator.ts +55 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/index.ts +14 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/internal/opfsWorker.ts +7 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/sqlite-wasm.d.ts +47 -0
- package/repos/effect/packages/sql/sqlite-wasm/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/sqlite-wasm/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-wasm/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/ai-codegen/codegen.schema.json +92 -0
- package/repos/effect/packages/tools/ai-codegen/docgen.json +4 -0
- package/repos/effect/packages/tools/ai-codegen/package.json +61 -0
- package/repos/effect/packages/tools/ai-codegen/src/Config.ts +292 -0
- package/repos/effect/packages/tools/ai-codegen/src/Discovery.ts +197 -0
- package/repos/effect/packages/tools/ai-codegen/src/Generator.ts +183 -0
- package/repos/effect/packages/tools/ai-codegen/src/Glob.ts +56 -0
- package/repos/effect/packages/tools/ai-codegen/src/PostProcess.ts +157 -0
- package/repos/effect/packages/tools/ai-codegen/src/SpecFetcher.ts +154 -0
- package/repos/effect/packages/tools/ai-codegen/src/bin.ts +10 -0
- package/repos/effect/packages/tools/ai-codegen/src/main.ts +237 -0
- package/repos/effect/packages/tools/ai-codegen/tsconfig.json +15 -0
- package/repos/effect/packages/tools/ai-docgen/docgen.json +4 -0
- package/repos/effect/packages/tools/ai-docgen/package.json +60 -0
- package/repos/effect/packages/tools/ai-docgen/src/Glob.ts +48 -0
- package/repos/effect/packages/tools/ai-docgen/src/main.ts +186 -0
- package/repos/effect/packages/tools/ai-docgen/tsconfig.json +14 -0
- package/repos/effect/packages/tools/bundle/docgen.json +4 -0
- package/repos/effect/packages/tools/bundle/fixtures/basic.ts +3 -0
- package/repos/effect/packages/tools/bundle/fixtures/batching.ts +25 -0
- package/repos/effect/packages/tools/bundle/fixtures/brand.ts +5 -0
- package/repos/effect/packages/tools/bundle/fixtures/cache.ts +10 -0
- package/repos/effect/packages/tools/bundle/fixtures/config.ts +13 -0
- package/repos/effect/packages/tools/bundle/fixtures/differ.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/http-client.ts +12 -0
- package/repos/effect/packages/tools/bundle/fixtures/logger.ts +5 -0
- package/repos/effect/packages/tools/bundle/fixtures/metric.ts +13 -0
- package/repos/effect/packages/tools/bundle/fixtures/optic.ts +6 -0
- package/repos/effect/packages/tools/bundle/fixtures/pubsub.ts +22 -0
- package/repos/effect/packages/tools/bundle/fixtures/queue.ts +18 -0
- package/repos/effect/packages/tools/bundle/fixtures/schedule.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-fromJsonSchemaDocument.ts +16 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-representation-roundtrip.ts +16 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-string-transformation.ts +20 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-string.ts +8 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-template-literal.ts +8 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toArbitraryLazy.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toCodeDocument.ts +12 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toCodecJson.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toEquivalence.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toFormatter.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toJsonSchemaDocument.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toRepresentation.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema.ts +12 -0
- package/repos/effect/packages/tools/bundle/fixtures/stm.ts +21 -0
- package/repos/effect/packages/tools/bundle/fixtures/stream.ts +7 -0
- package/repos/effect/packages/tools/bundle/package.json +52 -0
- package/repos/effect/packages/tools/bundle/src/Cli.ts +104 -0
- package/repos/effect/packages/tools/bundle/src/Fixtures.ts +51 -0
- package/repos/effect/packages/tools/bundle/src/Plugins.ts +131 -0
- package/repos/effect/packages/tools/bundle/src/Reporter.ts +200 -0
- package/repos/effect/packages/tools/bundle/src/Rollup.ts +179 -0
- package/repos/effect/packages/tools/bundle/src/bin.ts +23 -0
- package/repos/effect/packages/tools/bundle/tsconfig.fixtures.json +13 -0
- package/repos/effect/packages/tools/bundle/tsconfig.json +9 -0
- package/repos/effect/packages/tools/bundle/tsconfig.src.json +13 -0
- package/repos/effect/packages/tools/jsdocs/docgen.json +4 -0
- package/repos/effect/packages/tools/jsdocs/package.json +64 -0
- package/repos/effect/packages/tools/jsdocs/src/Jsdocs.ts +3303 -0
- package/repos/effect/packages/tools/jsdocs/src/bin.ts +23 -0
- package/repos/effect/packages/tools/jsdocs/test/jsdocs.test.ts +979 -0
- package/repos/effect/packages/tools/jsdocs/tsconfig.json +8 -0
- package/repos/effect/packages/tools/jsdocs/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/openapi-generator/CHANGELOG.md +691 -0
- package/repos/effect/packages/tools/openapi-generator/LICENSE +21 -0
- package/repos/effect/packages/tools/openapi-generator/docgen.json +4 -0
- package/repos/effect/packages/tools/openapi-generator/package.json +78 -0
- package/repos/effect/packages/tools/openapi-generator/src/HttpApiTransformer.ts +552 -0
- package/repos/effect/packages/tools/openapi-generator/src/JsonSchemaGenerator.ts +319 -0
- package/repos/effect/packages/tools/openapi-generator/src/OpenApiGenerator.ts +1201 -0
- package/repos/effect/packages/tools/openapi-generator/src/OpenApiPatch.ts +539 -0
- package/repos/effect/packages/tools/openapi-generator/src/OpenApiTransformer.ts +1019 -0
- package/repos/effect/packages/tools/openapi-generator/src/ParsedOperation.ts +277 -0
- package/repos/effect/packages/tools/openapi-generator/src/Utils.ts +111 -0
- package/repos/effect/packages/tools/openapi-generator/src/bin.ts +10 -0
- package/repos/effect/packages/tools/openapi-generator/src/main.ts +116 -0
- package/repos/effect/packages/tools/openapi-generator/test/JsonSchemaGenerator.test.ts +173 -0
- package/repos/effect/packages/tools/openapi-generator/test/OpenApiGenerator.test.ts +2130 -0
- package/repos/effect/packages/tools/openapi-generator/test/OpenApiGeneratorCli.test.ts +147 -0
- package/repos/effect/packages/tools/openapi-generator/test/OpenApiPatch.test.ts +380 -0
- package/repos/effect/packages/tools/openapi-generator/test/Utils.test.ts +33 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/cli-basic-spec.json +35 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/cli-warning-spec.json +57 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/invalid-op.json +7 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/missing-path.json +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/missing-value.json +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-add.json +8 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-multiple.json +17 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-patch.yaml +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-remove.json +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-replace.json +7 -0
- package/repos/effect/packages/tools/openapi-generator/tsconfig.json +9 -0
- package/repos/effect/packages/tools/openapi-generator/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/oxc/docgen.json +4 -0
- package/repos/effect/packages/tools/oxc/oxlintrc.json +83 -0
- package/repos/effect/packages/tools/oxc/package.json +72 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/index.ts +18 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/jsdocs.ts +108 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-bigint-literals.ts +25 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-import-from-barrel-package.ts +144 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-js-extension-imports.ts +73 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-opaque-instance-fields.ts +92 -0
- package/repos/effect/packages/tools/oxc/test/jsdocs.test.ts +75 -0
- package/repos/effect/packages/tools/oxc/test/no-import-from-barrel-package.test.ts +182 -0
- package/repos/effect/packages/tools/oxc/test/no-js-extension-imports.test.ts +120 -0
- package/repos/effect/packages/tools/oxc/test/no-opaque-instance-fields.test.ts +276 -0
- package/repos/effect/packages/tools/oxc/test/utils.ts +61 -0
- package/repos/effect/packages/tools/oxc/tsconfig.json +8 -0
- package/repos/effect/packages/tools/oxc/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/utils/docgen.json +4 -0
- package/repos/effect/packages/tools/utils/package.json +59 -0
- package/repos/effect/packages/tools/utils/src/Codegen.ts +214 -0
- package/repos/effect/packages/tools/utils/src/Glob.ts +61 -0
- package/repos/effect/packages/tools/utils/src/bin.ts +16 -0
- package/repos/effect/packages/tools/utils/src/commands/codegen.ts +44 -0
- package/repos/effect/packages/tools/utils/tsconfig.json +9 -0
- package/repos/effect/packages/vitest/CHANGELOG.md +601 -0
- package/repos/effect/packages/vitest/LICENSE +21 -0
- package/repos/effect/packages/vitest/README.md +320 -0
- package/repos/effect/packages/vitest/docgen.json +24 -0
- package/repos/effect/packages/vitest/package.json +60 -0
- package/repos/effect/packages/vitest/src/index.ts +259 -0
- package/repos/effect/packages/vitest/src/internal/internal.ts +374 -0
- package/repos/effect/packages/vitest/src/utils.ts +321 -0
- package/repos/effect/packages/vitest/test/index.test.ts +222 -0
- package/repos/effect/packages/vitest/test/isolation.test.ts +105 -0
- package/repos/effect/packages/vitest/test/nested-isolation.test.ts +212 -0
- package/repos/effect/packages/vitest/tsconfig.json +11 -0
- package/repos/effect/packages/vitest/typetest/index.tst.ts +56 -0
- package/repos/effect/packages/vitest/vitest.config.ts +6 -0
- package/repos/effect/patches/@changesets__assemble-release-plan.patch +26 -0
- package/repos/effect/patches/@changesets__get-github-info.patch +44 -0
- package/repos/effect/pnpm-lock.yaml +13483 -0
- package/repos/effect/pnpm-workspace.yaml +10 -0
- package/repos/effect/scripts/bundle-compare.sh +42 -0
- package/repos/effect/scripts/check-cookbook-schedule.ts +390 -0
- package/repos/effect/scripts/circular.mjs +26 -0
- package/repos/effect/scripts/clean.mjs +19 -0
- package/repos/effect/scripts/codemod.mjs +22 -0
- package/repos/effect/scripts/codemods/jsdoc.ts +79 -0
- package/repos/effect/scripts/docs.mjs +64 -0
- package/repos/effect/scripts/package-scalar.mjs +14 -0
- package/repos/effect/scripts/package-swagger.mjs +23 -0
- package/repos/effect/scripts/package.json +22 -0
- package/repos/effect/scripts/tsconfig.json +18 -0
- package/repos/effect/scripts/version.mjs +9 -0
- package/repos/effect/scripts/version.template.txt +2 -0
- package/repos/effect/scripts/worktree-setup.sh +27 -0
- package/repos/effect/stats.txt +30 -0
- package/repos/effect/tsconfig.base.json +46 -0
- package/repos/effect/tsconfig.json +128 -0
- package/repos/effect/tsconfig.packages.json +39 -0
- package/repos/effect/tstyche.json +7 -0
- package/repos/effect/vitest.config.ts +31 -0
- package/repos/effect/vitest.setup.ts +4 -0
- package/repos/effect/vitest.shared.ts +61 -0
- package/repos/effect.subtree.json +16 -0
|
@@ -0,0 +1,4058 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Records and reads measurements from Effect programs.
|
|
3
|
+
*
|
|
4
|
+
* A `Metric<Input, State>` accepts typed update values and stores an aggregated
|
|
5
|
+
* state that can be read directly or included in a snapshot. Metrics are used
|
|
6
|
+
* for counters, gauges, frequencies, histograms, summaries, and timers. This
|
|
7
|
+
* module includes metric constructors, update and read helpers, attributes,
|
|
8
|
+
* histogram boundaries, registry snapshots, text dumps, and controls for
|
|
9
|
+
* enabling runtime metrics.
|
|
10
|
+
*
|
|
11
|
+
* @since 2.0.0
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import * as Arr from "./Array.ts"
|
|
15
|
+
import * as Context from "./Context.ts"
|
|
16
|
+
import * as Duration from "./Duration.ts"
|
|
17
|
+
import type { Effect } from "./Effect.ts"
|
|
18
|
+
import type { Exit } from "./Exit.ts"
|
|
19
|
+
import { constUndefined, dual } from "./Function.ts"
|
|
20
|
+
import * as InternalEffect from "./internal/effect.ts"
|
|
21
|
+
import * as InternalMetric from "./internal/metric.ts"
|
|
22
|
+
import * as Layer from "./Layer.ts"
|
|
23
|
+
import * as Order from "./Order.ts"
|
|
24
|
+
import type { Pipeable } from "./Pipeable.ts"
|
|
25
|
+
import { pipeArguments } from "./Pipeable.ts"
|
|
26
|
+
import * as Predicate from "./Predicate.ts"
|
|
27
|
+
import * as _String from "./String.ts"
|
|
28
|
+
import type { Contravariant, Covariant } from "./Types.ts"
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A `Metric<Input, State>` represents a concurrent metric which accepts update
|
|
32
|
+
* values of type `Input` and are aggregated to a value of type `State`.
|
|
33
|
+
*
|
|
34
|
+
* **Details**
|
|
35
|
+
*
|
|
36
|
+
* For example, a counter metric would have type `Metric<number, number>`,
|
|
37
|
+
* representing the fact that the metric can be updated with numbers (the amount
|
|
38
|
+
* to increment or decrement the counter by), and the state of the counter is a
|
|
39
|
+
* number.
|
|
40
|
+
*
|
|
41
|
+
* There are five primitive metric types supported by Effect:
|
|
42
|
+
*
|
|
43
|
+
* - Counters
|
|
44
|
+
* - Frequencies
|
|
45
|
+
* - Gauges
|
|
46
|
+
* - Histograms
|
|
47
|
+
* - Summaries
|
|
48
|
+
*
|
|
49
|
+
* **Example** (Using multiple metric types)
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { Data, Effect, Metric } from "effect"
|
|
53
|
+
*
|
|
54
|
+
* class MetricExample extends Data.TaggedError("MetricExample")<{
|
|
55
|
+
* readonly operation: string
|
|
56
|
+
* }> {}
|
|
57
|
+
*
|
|
58
|
+
* const program = Effect.gen(function*() {
|
|
59
|
+
* // Create different types of metrics
|
|
60
|
+
* const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
|
|
61
|
+
* description: "Total requests processed"
|
|
62
|
+
* })
|
|
63
|
+
*
|
|
64
|
+
* const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
|
|
65
|
+
* description: "Current memory usage in MB"
|
|
66
|
+
* })
|
|
67
|
+
*
|
|
68
|
+
* const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
|
|
69
|
+
* description: "HTTP status code frequency"
|
|
70
|
+
* })
|
|
71
|
+
*
|
|
72
|
+
* // All metrics share the same interface for updates and reads
|
|
73
|
+
* yield* Metric.update(requestCounter, 1)
|
|
74
|
+
* yield* Metric.update(memoryGauge, 128)
|
|
75
|
+
* yield* Metric.update(statusFrequency, "200")
|
|
76
|
+
*
|
|
77
|
+
* // All metrics can be read with Metric.value
|
|
78
|
+
* const counterState = yield* Metric.value(requestCounter)
|
|
79
|
+
* const gaugeState = yield* Metric.value(memoryGauge)
|
|
80
|
+
* const frequencyState = yield* Metric.value(statusFrequency)
|
|
81
|
+
*
|
|
82
|
+
* // Metrics have common properties accessible through the interface:
|
|
83
|
+
* // - id: unique identifier
|
|
84
|
+
* // - type: metric type ("Counter", "Gauge", "Frequency", etc.)
|
|
85
|
+
* // - description: optional human-readable description
|
|
86
|
+
* // - attributes: optional key-value attributes for tagging
|
|
87
|
+
*
|
|
88
|
+
* return {
|
|
89
|
+
* counter: {
|
|
90
|
+
* id: requestCounter.id,
|
|
91
|
+
* type: requestCounter.type,
|
|
92
|
+
* state: counterState
|
|
93
|
+
* },
|
|
94
|
+
* gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
|
|
95
|
+
* frequency: {
|
|
96
|
+
* id: statusFrequency.id,
|
|
97
|
+
* type: statusFrequency.type,
|
|
98
|
+
* state: frequencyState
|
|
99
|
+
* }
|
|
100
|
+
* }
|
|
101
|
+
* })
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @category models
|
|
105
|
+
* @since 2.0.0
|
|
106
|
+
*/
|
|
107
|
+
export interface Metric<in Input, out State> extends Pipeable {
|
|
108
|
+
readonly [TypeId]: typeof TypeId
|
|
109
|
+
readonly Input: Contravariant<Input>
|
|
110
|
+
readonly State: Covariant<State>
|
|
111
|
+
readonly id: string
|
|
112
|
+
readonly type: Metric.Type
|
|
113
|
+
readonly description: string | undefined
|
|
114
|
+
readonly attributes: Metric.AttributeSet | undefined
|
|
115
|
+
readonly valueUnsafe: (context: Context.Context<never>) => State
|
|
116
|
+
readonly updateUnsafe: (input: Input, context: Context.Context<never>) => void
|
|
117
|
+
readonly modifyUnsafe: (input: Input, context: Context.Context<never>) => void
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* A Counter metric that tracks cumulative values that typically only increase.
|
|
122
|
+
*
|
|
123
|
+
* **When to use**
|
|
124
|
+
*
|
|
125
|
+
* Use when counters are useful for tracking monotonically increasing values like request counts,
|
|
126
|
+
* bytes processed, errors encountered, or any value that accumulates over time.
|
|
127
|
+
*
|
|
128
|
+
* **Example** (Using counter metrics)
|
|
129
|
+
*
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { Data, Effect, Metric } from "effect"
|
|
132
|
+
*
|
|
133
|
+
* class CounterInterfaceError extends Data.TaggedError("CounterInterfaceError")<{
|
|
134
|
+
* readonly operation: string
|
|
135
|
+
* }> {}
|
|
136
|
+
*
|
|
137
|
+
* const program = Effect.gen(function*() {
|
|
138
|
+
* // Create different types of counters
|
|
139
|
+
* const requestCounter: Metric.Counter<number> = Metric.counter(
|
|
140
|
+
* "http_requests",
|
|
141
|
+
* {
|
|
142
|
+
* description: "Total HTTP requests processed",
|
|
143
|
+
* incremental: true // Only allows increments
|
|
144
|
+
* }
|
|
145
|
+
* )
|
|
146
|
+
*
|
|
147
|
+
* const bytesCounter: Metric.Counter<bigint> = Metric.counter(
|
|
148
|
+
* "bytes_processed",
|
|
149
|
+
* {
|
|
150
|
+
* description: "Total bytes processed",
|
|
151
|
+
* bigint: true,
|
|
152
|
+
* attributes: { service: "data-processor" }
|
|
153
|
+
* }
|
|
154
|
+
* )
|
|
155
|
+
*
|
|
156
|
+
* // Update counters
|
|
157
|
+
* yield* Metric.update(requestCounter, 1) // Increment by 1
|
|
158
|
+
* yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
|
|
159
|
+
* yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
|
|
160
|
+
*
|
|
161
|
+
* // Read counter state
|
|
162
|
+
* const requestState: Metric.CounterState<number> = yield* Metric.value(
|
|
163
|
+
* requestCounter
|
|
164
|
+
* )
|
|
165
|
+
* const bytesState: Metric.CounterState<bigint> = yield* Metric.value(
|
|
166
|
+
* bytesCounter
|
|
167
|
+
* )
|
|
168
|
+
*
|
|
169
|
+
* // Counter state contains:
|
|
170
|
+
* // - count: current accumulated value
|
|
171
|
+
* // - incremental: whether only increments are allowed
|
|
172
|
+
*
|
|
173
|
+
* return {
|
|
174
|
+
* requests: {
|
|
175
|
+
* count: requestState.count,
|
|
176
|
+
* incremental: requestState.incremental
|
|
177
|
+
* },
|
|
178
|
+
* bytes: { count: bytesState.count, incremental: bytesState.incremental }
|
|
179
|
+
* }
|
|
180
|
+
* })
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @category metrics
|
|
184
|
+
* @since 2.0.0
|
|
185
|
+
*/
|
|
186
|
+
export interface Counter<in Input extends number | bigint> extends Metric<Input, CounterState<Input>> {}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* State interface for Counter metrics containing the current count and increment mode.
|
|
190
|
+
*
|
|
191
|
+
* **Example** (Reading counter state)
|
|
192
|
+
*
|
|
193
|
+
* ```ts
|
|
194
|
+
* import { Data, Effect, Metric } from "effect"
|
|
195
|
+
*
|
|
196
|
+
* class CounterStateError extends Data.TaggedError("CounterStateError")<{
|
|
197
|
+
* readonly operation: string
|
|
198
|
+
* }> {}
|
|
199
|
+
*
|
|
200
|
+
* const program = Effect.gen(function*() {
|
|
201
|
+
* // Create different types of counters
|
|
202
|
+
* const requestCounter = Metric.counter("http_requests_total")
|
|
203
|
+
* const errorCounter = Metric.counter("errors_total", { incremental: true })
|
|
204
|
+
* const byteCounter = Metric.counter("bytes_processed", { bigint: true })
|
|
205
|
+
*
|
|
206
|
+
* // Update counters
|
|
207
|
+
* yield* Metric.update(requestCounter, 5) // Add 5 requests
|
|
208
|
+
* yield* Metric.update(requestCounter, -2) // Subtract 2 (allowed for non-incremental)
|
|
209
|
+
* yield* Metric.update(errorCounter, 3) // Add 3 errors
|
|
210
|
+
* yield* Metric.update(errorCounter, -1) // Attempt to subtract (ignored for incremental)
|
|
211
|
+
* yield* Metric.update(byteCounter, 1024000n) // Add bytes as bigint
|
|
212
|
+
*
|
|
213
|
+
* // Read counter states
|
|
214
|
+
* const requestState: Metric.CounterState<number> = yield* Metric.value(
|
|
215
|
+
* requestCounter
|
|
216
|
+
* )
|
|
217
|
+
* const errorState: Metric.CounterState<number> = yield* Metric.value(
|
|
218
|
+
* errorCounter
|
|
219
|
+
* )
|
|
220
|
+
* const byteState: Metric.CounterState<bigint> = yield* Metric.value(
|
|
221
|
+
* byteCounter
|
|
222
|
+
* )
|
|
223
|
+
*
|
|
224
|
+
* // CounterState contains:
|
|
225
|
+
* // - count: current count value (number or bigint based on counter type)
|
|
226
|
+
* // - incremental: whether counter only allows increases
|
|
227
|
+
*
|
|
228
|
+
* return {
|
|
229
|
+
* requests: {
|
|
230
|
+
* total: requestState.count, // 3 (5 - 2, decrements allowed)
|
|
231
|
+
* canDecrease: !requestState.incremental // true
|
|
232
|
+
* },
|
|
233
|
+
* errors: {
|
|
234
|
+
* total: errorState.count, // 3 (subtract ignored)
|
|
235
|
+
* canDecrease: !errorState.incremental // false
|
|
236
|
+
* },
|
|
237
|
+
* bytes: {
|
|
238
|
+
* total: byteState.count, // 1024000n
|
|
239
|
+
* canDecrease: !byteState.incremental // true
|
|
240
|
+
* }
|
|
241
|
+
* }
|
|
242
|
+
* })
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @category Counter
|
|
246
|
+
* @since 4.0.0
|
|
247
|
+
*/
|
|
248
|
+
export interface CounterState<in Input extends number | bigint> {
|
|
249
|
+
readonly count: Input extends bigint ? bigint : number
|
|
250
|
+
readonly incremental: boolean
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* A Frequency metric interface that counts occurrences of discrete string values.
|
|
255
|
+
*
|
|
256
|
+
* **When to use**
|
|
257
|
+
*
|
|
258
|
+
* Use when frequency metrics are ideal for tracking categorical data where you want to count
|
|
259
|
+
* how many times specific string values occur, such as HTTP status codes, user actions,
|
|
260
|
+
* error types, or any discrete string-based events.
|
|
261
|
+
*
|
|
262
|
+
* **Example** (Using frequency metrics)
|
|
263
|
+
*
|
|
264
|
+
* ```ts
|
|
265
|
+
* import { Data, Effect, Metric } from "effect"
|
|
266
|
+
*
|
|
267
|
+
* class FrequencyInterfaceError
|
|
268
|
+
* extends Data.TaggedError("FrequencyInterfaceError")<{
|
|
269
|
+
* readonly operation: string
|
|
270
|
+
* }>
|
|
271
|
+
* {}
|
|
272
|
+
*
|
|
273
|
+
* // Function that accepts any Frequency metric
|
|
274
|
+
* const logFrequencyMetric = (freq: Metric.Frequency) =>
|
|
275
|
+
* Effect.gen(function*() {
|
|
276
|
+
* const state = yield* Metric.value(freq)
|
|
277
|
+
*
|
|
278
|
+
* yield* Effect.log(`Frequency Metric: ${freq.id}`)
|
|
279
|
+
* yield* Effect.log(`Description: ${freq.description ?? "No description"}`)
|
|
280
|
+
* yield* Effect.log(`Type: ${freq.type}`) // "Frequency"
|
|
281
|
+
*
|
|
282
|
+
* // Access the frequency state
|
|
283
|
+
* const occurrences: ReadonlyMap<string, number> = state.occurrences
|
|
284
|
+
* yield* Effect.log(`Total unique values: ${occurrences.size}`)
|
|
285
|
+
*
|
|
286
|
+
* // Iterate through all occurrences
|
|
287
|
+
* for (const [value, count] of occurrences) {
|
|
288
|
+
* yield* Effect.log(` "${value}": ${count} occurrences`)
|
|
289
|
+
* }
|
|
290
|
+
*
|
|
291
|
+
* // Find most frequent value
|
|
292
|
+
* let maxCount = 0
|
|
293
|
+
* let mostFrequent = ""
|
|
294
|
+
* for (const [value, count] of occurrences) {
|
|
295
|
+
* if (count > maxCount) {
|
|
296
|
+
* maxCount = count
|
|
297
|
+
* mostFrequent = value
|
|
298
|
+
* }
|
|
299
|
+
* }
|
|
300
|
+
*
|
|
301
|
+
* return { mostFrequent, maxCount, totalUniqueValues: occurrences.size }
|
|
302
|
+
* })
|
|
303
|
+
*
|
|
304
|
+
* const program = Effect.gen(function*() {
|
|
305
|
+
* // Create frequency metrics
|
|
306
|
+
* const statusCodes: Metric.Frequency = Metric.frequency("http_status", {
|
|
307
|
+
* description: "HTTP status code frequency"
|
|
308
|
+
* })
|
|
309
|
+
*
|
|
310
|
+
* const userActions: Metric.Frequency = Metric.frequency("user_actions", {
|
|
311
|
+
* description: "User action frequency"
|
|
312
|
+
* })
|
|
313
|
+
*
|
|
314
|
+
* // Record some occurrences
|
|
315
|
+
* yield* Metric.update(statusCodes, "200")
|
|
316
|
+
* yield* Metric.update(statusCodes, "200")
|
|
317
|
+
* yield* Metric.update(statusCodes, "404")
|
|
318
|
+
* yield* Metric.update(statusCodes, "500")
|
|
319
|
+
* yield* Metric.update(statusCodes, "200")
|
|
320
|
+
*
|
|
321
|
+
* yield* Metric.update(userActions, "login")
|
|
322
|
+
* yield* Metric.update(userActions, "view_dashboard")
|
|
323
|
+
* yield* Metric.update(userActions, "login")
|
|
324
|
+
*
|
|
325
|
+
* // Use the function with different frequency metrics
|
|
326
|
+
* const statusAnalysis = yield* logFrequencyMetric(statusCodes)
|
|
327
|
+
* const actionAnalysis = yield* logFrequencyMetric(userActions)
|
|
328
|
+
*
|
|
329
|
+
* return { statusAnalysis, actionAnalysis }
|
|
330
|
+
* })
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* @category metrics
|
|
334
|
+
* @since 2.0.0
|
|
335
|
+
*/
|
|
336
|
+
export interface Frequency extends Metric<string, FrequencyState> {}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* State interface for Frequency metrics containing occurrence counts for discrete string values.
|
|
340
|
+
*
|
|
341
|
+
* **Example** (Reading frequency state)
|
|
342
|
+
*
|
|
343
|
+
* ```ts
|
|
344
|
+
* import { Data, Effect, Metric } from "effect"
|
|
345
|
+
*
|
|
346
|
+
* class FrequencyStateError extends Data.TaggedError("FrequencyStateError")<{
|
|
347
|
+
* readonly operation: string
|
|
348
|
+
* }> {}
|
|
349
|
+
*
|
|
350
|
+
* const program = Effect.gen(function*() {
|
|
351
|
+
* // Create frequency metrics for different categories
|
|
352
|
+
* const statusCodeFreq = Metric.frequency("http_status_codes", {
|
|
353
|
+
* description: "HTTP status code distribution"
|
|
354
|
+
* })
|
|
355
|
+
*
|
|
356
|
+
* const userActionFreq = Metric.frequency("user_actions", {
|
|
357
|
+
* description: "User action frequency"
|
|
358
|
+
* })
|
|
359
|
+
*
|
|
360
|
+
* // Record occurrences
|
|
361
|
+
* yield* Metric.update(statusCodeFreq, "200") // Success
|
|
362
|
+
* yield* Metric.update(statusCodeFreq, "200") // Another success
|
|
363
|
+
* yield* Metric.update(statusCodeFreq, "404") // Not found
|
|
364
|
+
* yield* Metric.update(statusCodeFreq, "500") // Server error
|
|
365
|
+
* yield* Metric.update(statusCodeFreq, "200") // Another success
|
|
366
|
+
*
|
|
367
|
+
* yield* Metric.update(userActionFreq, "login")
|
|
368
|
+
* yield* Metric.update(userActionFreq, "click")
|
|
369
|
+
* yield* Metric.update(userActionFreq, "login")
|
|
370
|
+
* yield* Metric.update(userActionFreq, "scroll")
|
|
371
|
+
* yield* Metric.update(userActionFreq, "click")
|
|
372
|
+
* yield* Metric.update(userActionFreq, "click")
|
|
373
|
+
*
|
|
374
|
+
* // Read frequency states
|
|
375
|
+
* const statusState: Metric.FrequencyState = yield* Metric.value(statusCodeFreq)
|
|
376
|
+
* const actionState: Metric.FrequencyState = yield* Metric.value(userActionFreq)
|
|
377
|
+
*
|
|
378
|
+
* // FrequencyState contains:
|
|
379
|
+
* // - occurrences: ReadonlyMap<string, number> with string values and their counts
|
|
380
|
+
*
|
|
381
|
+
* // Analyze frequency distributions
|
|
382
|
+
* const getMostFrequent = (occurrences: ReadonlyMap<string, number>) => {
|
|
383
|
+
* let maxKey = ""
|
|
384
|
+
* let maxCount = 0
|
|
385
|
+
* for (const [key, count] of occurrences) {
|
|
386
|
+
* if (count > maxCount) {
|
|
387
|
+
* maxKey = key
|
|
388
|
+
* maxCount = count
|
|
389
|
+
* }
|
|
390
|
+
* }
|
|
391
|
+
* return { key: maxKey, count: maxCount }
|
|
392
|
+
* }
|
|
393
|
+
*
|
|
394
|
+
* const topStatus = getMostFrequent(statusState.occurrences)
|
|
395
|
+
* const topAction = getMostFrequent(actionState.occurrences)
|
|
396
|
+
*
|
|
397
|
+
* return {
|
|
398
|
+
* statusCodes: {
|
|
399
|
+
* totalResponses: Array.from(statusState.occurrences.values()).reduce(
|
|
400
|
+
* (a, b) => a + b,
|
|
401
|
+
* 0
|
|
402
|
+
* ), // 5
|
|
403
|
+
* mostCommon: topStatus, // { key: "200", count: 3 }
|
|
404
|
+
* uniqueCodes: statusState.occurrences.size // 3
|
|
405
|
+
* },
|
|
406
|
+
* userActions: {
|
|
407
|
+
* totalActions: Array.from(actionState.occurrences.values()).reduce(
|
|
408
|
+
* (a, b) => a + b,
|
|
409
|
+
* 0
|
|
410
|
+
* ), // 6
|
|
411
|
+
* mostCommon: topAction, // { key: "click", count: 3 }
|
|
412
|
+
* uniqueActions: actionState.occurrences.size // 3
|
|
413
|
+
* }
|
|
414
|
+
* }
|
|
415
|
+
* })
|
|
416
|
+
* ```
|
|
417
|
+
*
|
|
418
|
+
* @category metrics
|
|
419
|
+
* @since 4.0.0
|
|
420
|
+
*/
|
|
421
|
+
export interface FrequencyState {
|
|
422
|
+
readonly occurrences: ReadonlyMap<string, number>
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* A Gauge metric that tracks instantaneous values that can go up or down.
|
|
427
|
+
*
|
|
428
|
+
* **When to use**
|
|
429
|
+
*
|
|
430
|
+
* Use when gauges are useful for tracking current state values like memory usage, CPU load,
|
|
431
|
+
* active connections, queue sizes, or any value that represents a current level.
|
|
432
|
+
*
|
|
433
|
+
* **Example** (Using gauge metrics)
|
|
434
|
+
*
|
|
435
|
+
* ```ts
|
|
436
|
+
* import { Data, Effect, Metric } from "effect"
|
|
437
|
+
*
|
|
438
|
+
* class GaugeInterfaceError extends Data.TaggedError("GaugeInterfaceError")<{
|
|
439
|
+
* readonly operation: string
|
|
440
|
+
* }> {}
|
|
441
|
+
*
|
|
442
|
+
* const program = Effect.gen(function*() {
|
|
443
|
+
* // Create different types of gauges
|
|
444
|
+
* const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage_mb", {
|
|
445
|
+
* description: "Current memory usage in megabytes"
|
|
446
|
+
* })
|
|
447
|
+
*
|
|
448
|
+
* const diskSpaceGauge: Metric.Gauge<bigint> = Metric.gauge("disk_free_bytes", {
|
|
449
|
+
* description: "Available disk space in bytes",
|
|
450
|
+
* bigint: true,
|
|
451
|
+
* attributes: { mount: "/var" }
|
|
452
|
+
* })
|
|
453
|
+
*
|
|
454
|
+
* // Set gauge values (absolute values)
|
|
455
|
+
* yield* Metric.update(memoryGauge, 512) // Set to 512 MB
|
|
456
|
+
* yield* Metric.update(memoryGauge, 640) // Set to 640 MB (replaces 512)
|
|
457
|
+
* yield* Metric.update(diskSpaceGauge, 5000000000n) // Set to ~5GB free
|
|
458
|
+
*
|
|
459
|
+
* // Modify gauge values (relative changes)
|
|
460
|
+
* yield* Metric.modify(memoryGauge, 128) // Add 128 MB (total: 768)
|
|
461
|
+
* yield* Metric.modify(memoryGauge, -64) // Subtract 64 MB (total: 704)
|
|
462
|
+
*
|
|
463
|
+
* // Read gauge state
|
|
464
|
+
* const memoryState: Metric.GaugeState<number> = yield* Metric.value(
|
|
465
|
+
* memoryGauge
|
|
466
|
+
* )
|
|
467
|
+
* const diskState: Metric.GaugeState<bigint> = yield* Metric.value(
|
|
468
|
+
* diskSpaceGauge
|
|
469
|
+
* )
|
|
470
|
+
*
|
|
471
|
+
* // Gauge state contains:
|
|
472
|
+
* // - value: current instantaneous value
|
|
473
|
+
*
|
|
474
|
+
* return {
|
|
475
|
+
* memory: { currentValue: memoryState.value }, // 704
|
|
476
|
+
* disk: { currentValue: diskState.value } // 5000000000n
|
|
477
|
+
* }
|
|
478
|
+
* })
|
|
479
|
+
* ```
|
|
480
|
+
*
|
|
481
|
+
* @category metrics
|
|
482
|
+
* @since 2.0.0
|
|
483
|
+
*/
|
|
484
|
+
export interface Gauge<in Input extends number | bigint> extends Metric<Input, GaugeState<Input>> {}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* State interface for Gauge metrics containing the current instantaneous value.
|
|
488
|
+
*
|
|
489
|
+
* **Example** (Reading gauge state)
|
|
490
|
+
*
|
|
491
|
+
* ```ts
|
|
492
|
+
* import { Data, Effect, Metric } from "effect"
|
|
493
|
+
*
|
|
494
|
+
* class GaugeStateError extends Data.TaggedError("GaugeStateError")<{
|
|
495
|
+
* readonly operation: string
|
|
496
|
+
* }> {}
|
|
497
|
+
*
|
|
498
|
+
* const program = Effect.gen(function*() {
|
|
499
|
+
* // Create different types of gauges
|
|
500
|
+
* const temperatureGauge = Metric.gauge("room_temperature_celsius", {
|
|
501
|
+
* description: "Current room temperature"
|
|
502
|
+
* })
|
|
503
|
+
*
|
|
504
|
+
* const diskSpaceGauge = Metric.gauge("disk_usage_bytes", {
|
|
505
|
+
* description: "Current disk usage",
|
|
506
|
+
* bigint: true
|
|
507
|
+
* })
|
|
508
|
+
*
|
|
509
|
+
* const queueSizeGauge = Metric.gauge("queue_size", {
|
|
510
|
+
* description: "Current queue size"
|
|
511
|
+
* })
|
|
512
|
+
*
|
|
513
|
+
* // Set gauge values (absolute values)
|
|
514
|
+
* yield* Metric.update(temperatureGauge, 22.5) // Set to 22.5°C
|
|
515
|
+
* yield* Metric.update(diskSpaceGauge, 5000000000n) // Set to 5GB usage
|
|
516
|
+
* yield* Metric.update(queueSizeGauge, 10) // Set to 10 items
|
|
517
|
+
*
|
|
518
|
+
* // Update gauge values (new absolute values)
|
|
519
|
+
* yield* Metric.update(temperatureGauge, 23.1) // Temperature changed
|
|
520
|
+
* yield* Metric.update(queueSizeGauge, 15) // Queue grew
|
|
521
|
+
*
|
|
522
|
+
* // Read gauge states
|
|
523
|
+
* const tempState: Metric.GaugeState<number> = yield* Metric.value(
|
|
524
|
+
* temperatureGauge
|
|
525
|
+
* )
|
|
526
|
+
* const diskState: Metric.GaugeState<bigint> = yield* Metric.value(
|
|
527
|
+
* diskSpaceGauge
|
|
528
|
+
* )
|
|
529
|
+
* const queueState: Metric.GaugeState<number> = yield* Metric.value(
|
|
530
|
+
* queueSizeGauge
|
|
531
|
+
* )
|
|
532
|
+
*
|
|
533
|
+
* // GaugeState contains:
|
|
534
|
+
* // - value: current instantaneous value (number or bigint based on gauge type)
|
|
535
|
+
*
|
|
536
|
+
* return {
|
|
537
|
+
* environment: {
|
|
538
|
+
* temperature: tempState.value, // 23.1
|
|
539
|
+
* temperatureUnit: "°C"
|
|
540
|
+
* },
|
|
541
|
+
* system: {
|
|
542
|
+
* diskUsage: diskState.value, // 5000000000n
|
|
543
|
+
* diskUsageGB: Number(diskState.value) / 1_000_000_000, // 5
|
|
544
|
+
* queueSize: queueState.value // 15
|
|
545
|
+
* }
|
|
546
|
+
* }
|
|
547
|
+
* })
|
|
548
|
+
* ```
|
|
549
|
+
*
|
|
550
|
+
* @category metrics
|
|
551
|
+
* @since 4.0.0
|
|
552
|
+
*/
|
|
553
|
+
export interface GaugeState<in Input extends number | bigint> {
|
|
554
|
+
readonly value: Input extends bigint ? bigint : number
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* A Histogram metric that records observations in configurable buckets to analyze value distributions.
|
|
559
|
+
*
|
|
560
|
+
* **When to use**
|
|
561
|
+
*
|
|
562
|
+
* Use when histograms are ideal for measuring request durations, response sizes, and other continuous values
|
|
563
|
+
* where you need to understand the distribution of values rather than just aggregates.
|
|
564
|
+
*
|
|
565
|
+
* **Example** (Using histogram metrics)
|
|
566
|
+
*
|
|
567
|
+
* ```ts
|
|
568
|
+
* import { Data, Effect, Metric } from "effect"
|
|
569
|
+
*
|
|
570
|
+
* class HistogramInterfaceError
|
|
571
|
+
* extends Data.TaggedError("HistogramInterfaceError")<{
|
|
572
|
+
* readonly operation: string
|
|
573
|
+
* }>
|
|
574
|
+
* {}
|
|
575
|
+
*
|
|
576
|
+
* const program = Effect.gen(function*() {
|
|
577
|
+
* // Create histograms with different boundary strategies
|
|
578
|
+
* const responseTimeHistogram: Metric.Histogram<number> = Metric.histogram(
|
|
579
|
+
* "http_response_time_ms",
|
|
580
|
+
* {
|
|
581
|
+
* description: "HTTP response time distribution in milliseconds",
|
|
582
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 20 }) // 0, 50, 100, ..., 950
|
|
583
|
+
* }
|
|
584
|
+
* )
|
|
585
|
+
*
|
|
586
|
+
* const fileSizeHistogram: Metric.Histogram<number> = Metric.histogram(
|
|
587
|
+
* "file_size_bytes",
|
|
588
|
+
* {
|
|
589
|
+
* description: "File size distribution in bytes",
|
|
590
|
+
* boundaries: Metric.exponentialBoundaries({
|
|
591
|
+
* start: 1,
|
|
592
|
+
* factor: 2,
|
|
593
|
+
* count: 10
|
|
594
|
+
* }) // 1, 2, 4, 8, ..., 512
|
|
595
|
+
* }
|
|
596
|
+
* )
|
|
597
|
+
*
|
|
598
|
+
* // Record observations (values get placed into appropriate buckets)
|
|
599
|
+
* yield* Metric.update(responseTimeHistogram, 125) // Goes into 100-150ms bucket
|
|
600
|
+
* yield* Metric.update(responseTimeHistogram, 75) // Goes into 50-100ms bucket
|
|
601
|
+
* yield* Metric.update(responseTimeHistogram, 200) // Goes into 150-200ms bucket
|
|
602
|
+
* yield* Metric.update(responseTimeHistogram, 45) // Goes into 0-50ms bucket
|
|
603
|
+
*
|
|
604
|
+
* yield* Metric.update(fileSizeHistogram, 3) // Goes into 2-4 bytes bucket
|
|
605
|
+
* yield* Metric.update(fileSizeHistogram, 15) // Goes into 8-16 bytes bucket
|
|
606
|
+
* yield* Metric.update(fileSizeHistogram, 100) // Goes into 64-128 bytes bucket
|
|
607
|
+
*
|
|
608
|
+
* // Read histogram state
|
|
609
|
+
* const responseTimeState: Metric.HistogramState = yield* Metric.value(
|
|
610
|
+
* responseTimeHistogram
|
|
611
|
+
* )
|
|
612
|
+
* const fileSizeState: Metric.HistogramState = yield* Metric.value(
|
|
613
|
+
* fileSizeHistogram
|
|
614
|
+
* )
|
|
615
|
+
*
|
|
616
|
+
* // Histogram state contains:
|
|
617
|
+
* // - buckets: Array of [boundary, cumulativeCount] pairs
|
|
618
|
+
* // - count: total number of observations
|
|
619
|
+
* // - min: smallest observed value
|
|
620
|
+
* // - max: largest observed value
|
|
621
|
+
* // - sum: sum of all observed values
|
|
622
|
+
*
|
|
623
|
+
* return {
|
|
624
|
+
* responseTime: {
|
|
625
|
+
* totalRequests: responseTimeState.count, // 4
|
|
626
|
+
* fastestRequest: responseTimeState.min, // 45
|
|
627
|
+
* slowestRequest: responseTimeState.max, // 200
|
|
628
|
+
* totalTime: responseTimeState.sum, // 445
|
|
629
|
+
* averageTime: responseTimeState.sum / responseTimeState.count // 111.25
|
|
630
|
+
* },
|
|
631
|
+
* fileSize: {
|
|
632
|
+
* totalFiles: fileSizeState.count, // 3
|
|
633
|
+
* smallestFile: fileSizeState.min, // 3
|
|
634
|
+
* largestFile: fileSizeState.max, // 100
|
|
635
|
+
* totalBytes: fileSizeState.sum // 118
|
|
636
|
+
* }
|
|
637
|
+
* }
|
|
638
|
+
* })
|
|
639
|
+
* ```
|
|
640
|
+
*
|
|
641
|
+
* @category metrics
|
|
642
|
+
* @since 2.0.0
|
|
643
|
+
*/
|
|
644
|
+
export interface Histogram<Input> extends Metric<Input, HistogramState> {}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* State interface for Histogram metrics containing bucket distributions and aggregate statistics.
|
|
648
|
+
*
|
|
649
|
+
* **Example** (Reading histogram state)
|
|
650
|
+
*
|
|
651
|
+
* ```ts
|
|
652
|
+
* import { Data, Effect, Metric } from "effect"
|
|
653
|
+
*
|
|
654
|
+
* class HistogramStateError extends Data.TaggedError("HistogramStateError")<{
|
|
655
|
+
* readonly operation: string
|
|
656
|
+
* }> {}
|
|
657
|
+
*
|
|
658
|
+
* const program = Effect.gen(function*() {
|
|
659
|
+
* // Create histogram with linear boundaries
|
|
660
|
+
* const responseTimeHistogram = Metric.histogram("api_response_time_ms", {
|
|
661
|
+
* description: "API response time distribution",
|
|
662
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 100, count: 10 }) // 0, 100, 200, ..., 900
|
|
663
|
+
* })
|
|
664
|
+
*
|
|
665
|
+
* // Record observations
|
|
666
|
+
* yield* Metric.update(responseTimeHistogram, 50) // Fast response
|
|
667
|
+
* yield* Metric.update(responseTimeHistogram, 150) // Average response
|
|
668
|
+
* yield* Metric.update(responseTimeHistogram, 750) // Slow response
|
|
669
|
+
* yield* Metric.update(responseTimeHistogram, 250) // Average response
|
|
670
|
+
* yield* Metric.update(responseTimeHistogram, 95) // Fast response
|
|
671
|
+
*
|
|
672
|
+
* // Read histogram state
|
|
673
|
+
* const state: Metric.HistogramState = yield* Metric.value(
|
|
674
|
+
* responseTimeHistogram
|
|
675
|
+
* )
|
|
676
|
+
*
|
|
677
|
+
* // HistogramState contains:
|
|
678
|
+
* // - buckets: Array of [boundary, cumulativeCount] pairs showing distribution
|
|
679
|
+
* // - count: total number of observations
|
|
680
|
+
* // - min: smallest observed value
|
|
681
|
+
* // - max: largest observed value
|
|
682
|
+
* // - sum: sum of all observed values
|
|
683
|
+
*
|
|
684
|
+
* // Analyze bucket distribution
|
|
685
|
+
* const analyzeBuckets = (buckets: ReadonlyArray<[number, number]>) => {
|
|
686
|
+
* const analysis: Array<
|
|
687
|
+
* { range: string; count: number; percentage: number }
|
|
688
|
+
* > = []
|
|
689
|
+
* let previousCount = 0
|
|
690
|
+
* const totalCount = buckets[buckets.length - 1]?.[1] ?? 0
|
|
691
|
+
*
|
|
692
|
+
* for (let i = 0; i < buckets.length; i++) {
|
|
693
|
+
* const [boundary, cumulativeCount] = buckets[i]
|
|
694
|
+
* const bucketCount = cumulativeCount - previousCount
|
|
695
|
+
* const percentage = totalCount > 0 ? (bucketCount / totalCount) * 100 : 0
|
|
696
|
+
* const prevBoundary = i === 0 ? 0 : buckets[i - 1][0]
|
|
697
|
+
*
|
|
698
|
+
* analysis.push({
|
|
699
|
+
* range: `${prevBoundary}-${boundary}ms`,
|
|
700
|
+
* count: bucketCount,
|
|
701
|
+
* percentage: Math.round(percentage * 10) / 10
|
|
702
|
+
* })
|
|
703
|
+
* previousCount = cumulativeCount
|
|
704
|
+
* }
|
|
705
|
+
* return analysis
|
|
706
|
+
* }
|
|
707
|
+
*
|
|
708
|
+
* const bucketAnalysis = analyzeBuckets(state.buckets)
|
|
709
|
+
*
|
|
710
|
+
* return {
|
|
711
|
+
* responseTime: {
|
|
712
|
+
* totalRequests: state.count, // 5
|
|
713
|
+
* fastestResponse: state.min, // 50
|
|
714
|
+
* slowestResponse: state.max, // 750
|
|
715
|
+
* averageResponse: state.sum / state.count, // 268
|
|
716
|
+
* totalTime: state.sum, // 1340
|
|
717
|
+
* distribution: bucketAnalysis
|
|
718
|
+
* // Example distribution:
|
|
719
|
+
* // [{ range: "0-100ms", count: 2, percentage: 40.0 },
|
|
720
|
+
* // { range: "100-200ms", count: 1, percentage: 20.0 },
|
|
721
|
+
* // { range: "200-300ms", count: 1, percentage: 20.0 },
|
|
722
|
+
* // { range: "700-800ms", count: 1, percentage: 20.0 }]
|
|
723
|
+
* }
|
|
724
|
+
* }
|
|
725
|
+
* })
|
|
726
|
+
* ```
|
|
727
|
+
*
|
|
728
|
+
* @category metrics
|
|
729
|
+
* @since 4.0.0
|
|
730
|
+
*/
|
|
731
|
+
export interface HistogramState {
|
|
732
|
+
readonly buckets: ReadonlyArray<[number, number]>
|
|
733
|
+
readonly count: number
|
|
734
|
+
readonly min: number
|
|
735
|
+
readonly max: number
|
|
736
|
+
readonly sum: number
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* A Summary metric that calculates quantiles over a sliding time window of observations.
|
|
741
|
+
*
|
|
742
|
+
* **When to use**
|
|
743
|
+
*
|
|
744
|
+
* Use when summaries provide statistical insights into value distributions by tracking specific quantiles
|
|
745
|
+
* (percentiles) such as median (50th), 95th percentile, 99th percentile, etc. They're ideal for
|
|
746
|
+
* understanding performance characteristics like response time distributions.
|
|
747
|
+
*
|
|
748
|
+
* **Example** (Using summary metrics)
|
|
749
|
+
*
|
|
750
|
+
* ```ts
|
|
751
|
+
* import { Data, Effect, Metric } from "effect"
|
|
752
|
+
*
|
|
753
|
+
* class SummaryInterfaceError extends Data.TaggedError("SummaryInterfaceError")<{
|
|
754
|
+
* readonly operation: string
|
|
755
|
+
* }> {}
|
|
756
|
+
*
|
|
757
|
+
* const program = Effect.gen(function*() {
|
|
758
|
+
* // Create summaries with different quantile configurations
|
|
759
|
+
* const responseTimeSummary: Metric.Summary<number> = Metric.summary(
|
|
760
|
+
* "api_response_time_ms",
|
|
761
|
+
* {
|
|
762
|
+
* description: "API response time distribution in milliseconds",
|
|
763
|
+
* maxAge: "5 minutes", // Keep observations for 5 minutes
|
|
764
|
+
* maxSize: 1000, // Keep up to 1000 observations
|
|
765
|
+
* quantiles: [0.5, 0.95, 0.99] // Track median, 95th, and 99th percentiles
|
|
766
|
+
* }
|
|
767
|
+
* )
|
|
768
|
+
*
|
|
769
|
+
* const requestSizeSummary: Metric.Summary<number> = Metric.summary(
|
|
770
|
+
* "request_size_bytes",
|
|
771
|
+
* {
|
|
772
|
+
* description: "Request payload size distribution",
|
|
773
|
+
* maxAge: "10 minutes",
|
|
774
|
+
* maxSize: 500,
|
|
775
|
+
* quantiles: [0.25, 0.5, 0.75, 0.9] // Track quartiles and 90th percentile
|
|
776
|
+
* }
|
|
777
|
+
* )
|
|
778
|
+
*
|
|
779
|
+
* // Record observations (values are stored in time-based sliding window)
|
|
780
|
+
* yield* Metric.update(responseTimeSummary, 120) // Fast response
|
|
781
|
+
* yield* Metric.update(responseTimeSummary, 250) // Average response
|
|
782
|
+
* yield* Metric.update(responseTimeSummary, 45) // Very fast response
|
|
783
|
+
* yield* Metric.update(responseTimeSummary, 890) // Slow response
|
|
784
|
+
* yield* Metric.update(responseTimeSummary, 156) // Average response
|
|
785
|
+
*
|
|
786
|
+
* yield* Metric.update(requestSizeSummary, 1024) // 1KB request
|
|
787
|
+
* yield* Metric.update(requestSizeSummary, 512) // 512B request
|
|
788
|
+
* yield* Metric.update(requestSizeSummary, 2048) // 2KB request
|
|
789
|
+
*
|
|
790
|
+
* // Read summary state
|
|
791
|
+
* const responseTimeState: Metric.SummaryState = yield* Metric.value(
|
|
792
|
+
* responseTimeSummary
|
|
793
|
+
* )
|
|
794
|
+
* const requestSizeState: Metric.SummaryState = yield* Metric.value(
|
|
795
|
+
* requestSizeSummary
|
|
796
|
+
* )
|
|
797
|
+
*
|
|
798
|
+
* // Summary state contains:
|
|
799
|
+
* // - quantiles: Array of [quantile, optionalValue] pairs
|
|
800
|
+
* // - count: total number of observations in window
|
|
801
|
+
* // - min: smallest observed value in window
|
|
802
|
+
* // - max: largest observed value in window
|
|
803
|
+
* // - sum: sum of all observed values in window
|
|
804
|
+
*
|
|
805
|
+
* // Extract quantile values safely
|
|
806
|
+
* const getQuantileValue = (
|
|
807
|
+
* quantiles: ReadonlyArray<readonly [number, number | undefined]>,
|
|
808
|
+
* q: number
|
|
809
|
+
* ) => quantiles.find(([quantile]) => quantile === q)?.[1]
|
|
810
|
+
*
|
|
811
|
+
* const median = getQuantileValue(responseTimeState.quantiles, 0.5)
|
|
812
|
+
* const p95 = getQuantileValue(responseTimeState.quantiles, 0.95)
|
|
813
|
+
* const p99 = getQuantileValue(responseTimeState.quantiles, 0.99)
|
|
814
|
+
*
|
|
815
|
+
* return {
|
|
816
|
+
* responseTime: {
|
|
817
|
+
* totalRequests: responseTimeState.count, // 5
|
|
818
|
+
* fastestResponse: responseTimeState.min, // 45
|
|
819
|
+
* slowestResponse: responseTimeState.max, // 890
|
|
820
|
+
* totalTime: responseTimeState.sum, // 1461
|
|
821
|
+
* averageTime: responseTimeState.sum / responseTimeState.count, // 292.2
|
|
822
|
+
* medianTime: median ?? null, // ~156
|
|
823
|
+
* p95Time: p95 ?? null, // ~890
|
|
824
|
+
* p99Time: p99 ?? null // ~890
|
|
825
|
+
* },
|
|
826
|
+
* requestSize: {
|
|
827
|
+
* totalRequests: requestSizeState.count, // 3
|
|
828
|
+
* averageSize: requestSizeState.sum / requestSizeState.count // ~1194.7
|
|
829
|
+
* }
|
|
830
|
+
* }
|
|
831
|
+
* })
|
|
832
|
+
* ```
|
|
833
|
+
*
|
|
834
|
+
* @category metrics
|
|
835
|
+
* @since 2.0.0
|
|
836
|
+
*/
|
|
837
|
+
export interface Summary<Input> extends Metric<Input, SummaryState> {}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* State interface for Summary metrics containing quantile calculations and aggregate statistics.
|
|
841
|
+
*
|
|
842
|
+
* **Example** (Reading summary state)
|
|
843
|
+
*
|
|
844
|
+
* ```ts
|
|
845
|
+
* import { Data, Effect, Metric } from "effect"
|
|
846
|
+
*
|
|
847
|
+
* class SummaryStateError extends Data.TaggedError("SummaryStateError")<{
|
|
848
|
+
* readonly operation: string
|
|
849
|
+
* }> {}
|
|
850
|
+
*
|
|
851
|
+
* const program = Effect.gen(function*() {
|
|
852
|
+
* // Create summary with specific quantiles
|
|
853
|
+
* const responseTimeSummary = Metric.summary("api_response_latency", {
|
|
854
|
+
* description: "API response time distribution with quantiles",
|
|
855
|
+
* maxAge: "5 minutes",
|
|
856
|
+
* maxSize: 1000,
|
|
857
|
+
* quantiles: [0.5, 0.95, 0.99] // Track median, 95th, and 99th percentiles
|
|
858
|
+
* })
|
|
859
|
+
*
|
|
860
|
+
* // Record observations over time
|
|
861
|
+
* yield* Metric.update(responseTimeSummary, 120) // Fast response
|
|
862
|
+
* yield* Metric.update(responseTimeSummary, 250) // Average response
|
|
863
|
+
* yield* Metric.update(responseTimeSummary, 45) // Very fast response
|
|
864
|
+
* yield* Metric.update(responseTimeSummary, 890) // Slow response
|
|
865
|
+
* yield* Metric.update(responseTimeSummary, 156) // Average response
|
|
866
|
+
* yield* Metric.update(responseTimeSummary, 78) // Fast response
|
|
867
|
+
* yield* Metric.update(responseTimeSummary, 340) // Slower response
|
|
868
|
+
*
|
|
869
|
+
* // Read summary state
|
|
870
|
+
* const state: Metric.SummaryState = yield* Metric.value(responseTimeSummary)
|
|
871
|
+
*
|
|
872
|
+
* // SummaryState contains:
|
|
873
|
+
* // - quantiles: Array of [quantile, optionalValue] pairs showing percentile values
|
|
874
|
+
* // - count: total number of observations in current window
|
|
875
|
+
* // - min: smallest observed value in window
|
|
876
|
+
* // - max: largest observed value in window
|
|
877
|
+
* // - sum: sum of all observed values in window
|
|
878
|
+
*
|
|
879
|
+
* // Extract quantile information safely
|
|
880
|
+
* const extractQuantiles = (
|
|
881
|
+
* quantiles: ReadonlyArray<readonly [number, number | undefined]>
|
|
882
|
+
* ) => {
|
|
883
|
+
* const result: Record<string, number | null> = {}
|
|
884
|
+
* for (const [quantile, valueOption] of quantiles) {
|
|
885
|
+
* const percentile = Math.round(quantile * 100)
|
|
886
|
+
* result[`p${percentile}`] = valueOption ?? null
|
|
887
|
+
* }
|
|
888
|
+
* return result
|
|
889
|
+
* }
|
|
890
|
+
*
|
|
891
|
+
* const quantileValues = extractQuantiles(state.quantiles)
|
|
892
|
+
*
|
|
893
|
+
* return {
|
|
894
|
+
* latencyAnalysis: {
|
|
895
|
+
* totalRequests: state.count, // 7
|
|
896
|
+
* fastestResponse: state.min, // 45
|
|
897
|
+
* slowestResponse: state.max, // 890
|
|
898
|
+
* averageResponse: state.sum / state.count, // ~268.4
|
|
899
|
+
* totalLatency: state.sum, // 1879
|
|
900
|
+
* percentiles: quantileValues,
|
|
901
|
+
* // Example percentiles:
|
|
902
|
+
* // { p50: 156, p95: 890, p99: 890 }
|
|
903
|
+
* performance: {
|
|
904
|
+
* fast: quantileValues.p50 !== null && quantileValues.p50 < 200
|
|
905
|
+
* ? "Good"
|
|
906
|
+
* : "Needs improvement",
|
|
907
|
+
* reliability: quantileValues.p95 !== null && quantileValues.p95 < 500
|
|
908
|
+
* ? "Reliable"
|
|
909
|
+
* : "Concerning"
|
|
910
|
+
* }
|
|
911
|
+
* }
|
|
912
|
+
* }
|
|
913
|
+
* })
|
|
914
|
+
* ```
|
|
915
|
+
*
|
|
916
|
+
* @category metrics
|
|
917
|
+
* @since 4.0.0
|
|
918
|
+
*/
|
|
919
|
+
export interface SummaryState {
|
|
920
|
+
readonly quantiles: ReadonlyArray<readonly [number, number | undefined]>
|
|
921
|
+
readonly count: number
|
|
922
|
+
readonly min: number
|
|
923
|
+
readonly max: number
|
|
924
|
+
readonly sum: number
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* The `Metric` namespace provides a comprehensive system for collecting, aggregating, and observing
|
|
929
|
+
* application metrics in Effect applications.
|
|
930
|
+
*
|
|
931
|
+
* **Example** (Collecting application metrics)
|
|
932
|
+
*
|
|
933
|
+
* ```ts
|
|
934
|
+
* import { Data, Effect, Metric } from "effect"
|
|
935
|
+
*
|
|
936
|
+
* class MetricsError extends Data.TaggedError("MetricsError")<{
|
|
937
|
+
* readonly operation: string
|
|
938
|
+
* }> {}
|
|
939
|
+
*
|
|
940
|
+
* const program = Effect.gen(function*() {
|
|
941
|
+
* // Create different types of metrics
|
|
942
|
+
* const requestCounter = Metric.counter("http_requests_total")
|
|
943
|
+
* const responseTimeHistogram = Metric.histogram("http_response_time", {
|
|
944
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
|
|
945
|
+
* })
|
|
946
|
+
* const activeConnectionsGauge = Metric.gauge("active_connections")
|
|
947
|
+
* const statusFrequency = Metric.frequency("http_status_codes")
|
|
948
|
+
*
|
|
949
|
+
* // Update metrics
|
|
950
|
+
* yield* Metric.update(requestCounter, 1)
|
|
951
|
+
* yield* Metric.update(responseTimeHistogram, 45.2)
|
|
952
|
+
* yield* Metric.update(activeConnectionsGauge, 12)
|
|
953
|
+
* yield* Metric.update(statusFrequency, "200")
|
|
954
|
+
*
|
|
955
|
+
* // Get metric values
|
|
956
|
+
* const counterValue = yield* Metric.value(requestCounter)
|
|
957
|
+
* const histogramValue = yield* Metric.value(responseTimeHistogram)
|
|
958
|
+
* const gaugeValue = yield* Metric.value(activeConnectionsGauge)
|
|
959
|
+
* const frequencyValue = yield* Metric.value(statusFrequency)
|
|
960
|
+
*
|
|
961
|
+
* return {
|
|
962
|
+
* counter: counterValue,
|
|
963
|
+
* histogram: histogramValue,
|
|
964
|
+
* gauge: gaugeValue,
|
|
965
|
+
* frequency: frequencyValue
|
|
966
|
+
* }
|
|
967
|
+
* })
|
|
968
|
+
* ```
|
|
969
|
+
*
|
|
970
|
+
* @since 2.0.0
|
|
971
|
+
*/
|
|
972
|
+
export declare namespace Metric {
|
|
973
|
+
/**
|
|
974
|
+
* Union type representing all available metric types in the Effect metrics system.
|
|
975
|
+
*
|
|
976
|
+
* **Example** (Inspecting metric types)
|
|
977
|
+
*
|
|
978
|
+
* ```ts
|
|
979
|
+
* import { Data, Effect, Metric } from "effect"
|
|
980
|
+
*
|
|
981
|
+
* class MetricTypeError extends Data.TaggedError("MetricTypeError")<{
|
|
982
|
+
* readonly operation: string
|
|
983
|
+
* }> {}
|
|
984
|
+
*
|
|
985
|
+
* const program = Effect.gen(function*() {
|
|
986
|
+
* // Create different metric types
|
|
987
|
+
* const counter = Metric.counter("requests_total")
|
|
988
|
+
* const gauge = Metric.gauge("cpu_usage")
|
|
989
|
+
* const frequency = Metric.frequency("status_codes")
|
|
990
|
+
* const histogram = Metric.histogram("response_time", {
|
|
991
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 10 })
|
|
992
|
+
* })
|
|
993
|
+
* const summary = Metric.summary("latency", {
|
|
994
|
+
* maxAge: "5 minutes",
|
|
995
|
+
* maxSize: 1000,
|
|
996
|
+
* quantiles: [0.5, 0.95, 0.99]
|
|
997
|
+
* })
|
|
998
|
+
*
|
|
999
|
+
* // Function that checks metric type
|
|
1000
|
+
* const getMetricInfo = (metric: Metric.Metric<any, any>) => ({
|
|
1001
|
+
* name: metric.id,
|
|
1002
|
+
* type: metric.type
|
|
1003
|
+
* })
|
|
1004
|
+
*
|
|
1005
|
+
* // Get type information for each metric
|
|
1006
|
+
* const counterInfo = getMetricInfo(counter) // { name: "requests_total", type: "Counter" }
|
|
1007
|
+
* const gaugeInfo = getMetricInfo(gauge) // { name: "cpu_usage", type: "Gauge" }
|
|
1008
|
+
* const frequencyInfo = getMetricInfo(frequency) // { name: "status_codes", type: "Frequency" }
|
|
1009
|
+
* const histogramInfo = getMetricInfo(histogram) // { name: "response_time", type: "Histogram" }
|
|
1010
|
+
* const summaryInfo = getMetricInfo(summary) // { name: "latency", type: "Summary" }
|
|
1011
|
+
*
|
|
1012
|
+
* // Pattern match on metric type
|
|
1013
|
+
* const describeMetric = (type: string): string => {
|
|
1014
|
+
* switch (type) {
|
|
1015
|
+
* case "Counter":
|
|
1016
|
+
* return "Cumulative values that increase over time"
|
|
1017
|
+
* case "Gauge":
|
|
1018
|
+
* return "Instantaneous values that can go up or down"
|
|
1019
|
+
* case "Frequency":
|
|
1020
|
+
* return "Counts of discrete string occurrences"
|
|
1021
|
+
* case "Histogram":
|
|
1022
|
+
* return "Distribution of values across buckets"
|
|
1023
|
+
* case "Summary":
|
|
1024
|
+
* return "Quantile calculations over time windows"
|
|
1025
|
+
* default:
|
|
1026
|
+
* return "Unknown metric type"
|
|
1027
|
+
* }
|
|
1028
|
+
* }
|
|
1029
|
+
*
|
|
1030
|
+
* return {
|
|
1031
|
+
* metrics: [
|
|
1032
|
+
* counterInfo,
|
|
1033
|
+
* gaugeInfo,
|
|
1034
|
+
* frequencyInfo,
|
|
1035
|
+
* histogramInfo,
|
|
1036
|
+
* summaryInfo
|
|
1037
|
+
* ],
|
|
1038
|
+
* descriptions: {
|
|
1039
|
+
* Counter: describeMetric("Counter"),
|
|
1040
|
+
* Gauge: describeMetric("Gauge"),
|
|
1041
|
+
* Frequency: describeMetric("Frequency"),
|
|
1042
|
+
* Histogram: describeMetric("Histogram"),
|
|
1043
|
+
* Summary: describeMetric("Summary")
|
|
1044
|
+
* }
|
|
1045
|
+
* }
|
|
1046
|
+
* })
|
|
1047
|
+
* ```
|
|
1048
|
+
*
|
|
1049
|
+
* @category types
|
|
1050
|
+
* @since 4.0.0
|
|
1051
|
+
*/
|
|
1052
|
+
export type Type = "Counter" | "Frequency" | "Gauge" | "Histogram" | "Summary"
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* Union type for metric attributes that can be provided as either an object or array of tuples.
|
|
1056
|
+
*
|
|
1057
|
+
* **Example** (Providing attributes in different formats)
|
|
1058
|
+
*
|
|
1059
|
+
* ```ts
|
|
1060
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1061
|
+
*
|
|
1062
|
+
* class AttributesError extends Data.TaggedError("AttributesError")<{
|
|
1063
|
+
* readonly operation: string
|
|
1064
|
+
* }> {}
|
|
1065
|
+
*
|
|
1066
|
+
* const program = Effect.gen(function*() {
|
|
1067
|
+
* // Different ways to specify attributes
|
|
1068
|
+
* const attributesAsObject = {
|
|
1069
|
+
* service: "api",
|
|
1070
|
+
* environment: "production",
|
|
1071
|
+
* version: "1.2.3"
|
|
1072
|
+
* }
|
|
1073
|
+
*
|
|
1074
|
+
* const attributesAsArray: ReadonlyArray<[string, string]> = [
|
|
1075
|
+
* ["service", "api"],
|
|
1076
|
+
* ["environment", "production"],
|
|
1077
|
+
* ["version", "1.2.3"]
|
|
1078
|
+
* ]
|
|
1079
|
+
*
|
|
1080
|
+
* // Create metrics with different attribute formats
|
|
1081
|
+
* const requestCounter1 = Metric.counter("requests", {
|
|
1082
|
+
* description: "Total requests",
|
|
1083
|
+
* attributes: attributesAsObject // Using object format
|
|
1084
|
+
* })
|
|
1085
|
+
*
|
|
1086
|
+
* const requestCounter2 = Metric.counter("requests", {
|
|
1087
|
+
* description: "Total requests",
|
|
1088
|
+
* attributes: attributesAsArray // Using array format
|
|
1089
|
+
* })
|
|
1090
|
+
*
|
|
1091
|
+
* // Function to normalize attributes to object format
|
|
1092
|
+
* const normalizeAttributes = (
|
|
1093
|
+
* attrs: typeof attributesAsObject | ReadonlyArray<[string, string]>
|
|
1094
|
+
* ) => {
|
|
1095
|
+
* if (Array.isArray(attrs)) {
|
|
1096
|
+
* return Object.fromEntries(attrs)
|
|
1097
|
+
* }
|
|
1098
|
+
* return attrs
|
|
1099
|
+
* }
|
|
1100
|
+
*
|
|
1101
|
+
* // Add runtime attributes using withAttributes
|
|
1102
|
+
* const contextualCounter = Metric.withAttributes(requestCounter1, {
|
|
1103
|
+
* method: "GET",
|
|
1104
|
+
* endpoint: "/api/users"
|
|
1105
|
+
* })
|
|
1106
|
+
*
|
|
1107
|
+
* // Update metrics with different attribute combinations
|
|
1108
|
+
* yield* Metric.update(contextualCounter, 1)
|
|
1109
|
+
*
|
|
1110
|
+
* // Both formats result in the same internal representation
|
|
1111
|
+
* const normalizedObject = normalizeAttributes(attributesAsObject)
|
|
1112
|
+
* const normalizedArray = normalizeAttributes(attributesAsArray)
|
|
1113
|
+
*
|
|
1114
|
+
* return {
|
|
1115
|
+
* attributeFormats: {
|
|
1116
|
+
* object: normalizedObject, // { service: "api", environment: "production", version: "1.2.3" }
|
|
1117
|
+
* array: normalizedArray, // { service: "api", environment: "production", version: "1.2.3" }
|
|
1118
|
+
* areEqual:
|
|
1119
|
+
* JSON.stringify(normalizedObject) === JSON.stringify(normalizedArray) // true
|
|
1120
|
+
* }
|
|
1121
|
+
* }
|
|
1122
|
+
* })
|
|
1123
|
+
* ```
|
|
1124
|
+
*
|
|
1125
|
+
* @category types
|
|
1126
|
+
* @since 4.0.0
|
|
1127
|
+
*/
|
|
1128
|
+
export type Attributes = AttributeSet | ReadonlyArray<[string, string]>
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Type for metric attributes as a readonly record of string key-value pairs.
|
|
1132
|
+
*
|
|
1133
|
+
* **Example** (Combining metric attribute sets)
|
|
1134
|
+
*
|
|
1135
|
+
* ```ts
|
|
1136
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1137
|
+
*
|
|
1138
|
+
* class AttributeSetError extends Data.TaggedError("AttributeSetError")<{
|
|
1139
|
+
* readonly operation: string
|
|
1140
|
+
* }> {}
|
|
1141
|
+
*
|
|
1142
|
+
* const program = Effect.gen(function*() {
|
|
1143
|
+
* // Define attribute sets for different contexts
|
|
1144
|
+
* const serviceAttributes = {
|
|
1145
|
+
* service: "user-api",
|
|
1146
|
+
* version: "2.1.0",
|
|
1147
|
+
* environment: "production"
|
|
1148
|
+
* }
|
|
1149
|
+
*
|
|
1150
|
+
* const operationAttributes = {
|
|
1151
|
+
* operation: "create_user",
|
|
1152
|
+
* method: "POST",
|
|
1153
|
+
* endpoint: "/api/users"
|
|
1154
|
+
* }
|
|
1155
|
+
*
|
|
1156
|
+
* const infrastructureAttributes = {
|
|
1157
|
+
* region: "us-east-1",
|
|
1158
|
+
* datacenter: "dc1",
|
|
1159
|
+
* host: "api-server-01"
|
|
1160
|
+
* }
|
|
1161
|
+
*
|
|
1162
|
+
* // Create metrics with predefined attribute sets
|
|
1163
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
1164
|
+
* description: "Total HTTP requests",
|
|
1165
|
+
* attributes: serviceAttributes
|
|
1166
|
+
* })
|
|
1167
|
+
*
|
|
1168
|
+
* // Combine attribute sets
|
|
1169
|
+
* const combineAttributes = (...attributeSets: Array<Record<string, string>>) =>
|
|
1170
|
+
* Object.assign({}, ...attributeSets)
|
|
1171
|
+
*
|
|
1172
|
+
* const fullAttributes = combineAttributes(
|
|
1173
|
+
* serviceAttributes,
|
|
1174
|
+
* operationAttributes,
|
|
1175
|
+
* infrastructureAttributes
|
|
1176
|
+
* )
|
|
1177
|
+
*
|
|
1178
|
+
* // Create metric with combined attributes
|
|
1179
|
+
* const detailedCounter = Metric.withAttributes(requestCounter, fullAttributes)
|
|
1180
|
+
*
|
|
1181
|
+
* // Helper to validate attribute keys (all must be strings)
|
|
1182
|
+
* const validateAttributeSet = (attrs: Record<string, string>): boolean => {
|
|
1183
|
+
* return Object.entries(attrs).every(([key, value]) =>
|
|
1184
|
+
* typeof key === "string" && typeof value === "string"
|
|
1185
|
+
* )
|
|
1186
|
+
* }
|
|
1187
|
+
*
|
|
1188
|
+
* yield* Metric.update(detailedCounter, 1)
|
|
1189
|
+
*
|
|
1190
|
+
* return {
|
|
1191
|
+
* attributes: {
|
|
1192
|
+
* service: serviceAttributes,
|
|
1193
|
+
* operation: operationAttributes,
|
|
1194
|
+
* infrastructure: infrastructureAttributes,
|
|
1195
|
+
* combined: fullAttributes,
|
|
1196
|
+
* isValid: validateAttributeSet(fullAttributes), // true
|
|
1197
|
+
* totalKeys: Object.keys(fullAttributes).length // 9
|
|
1198
|
+
* }
|
|
1199
|
+
* }
|
|
1200
|
+
* })
|
|
1201
|
+
* ```
|
|
1202
|
+
*
|
|
1203
|
+
* @category types
|
|
1204
|
+
* @since 4.0.0
|
|
1205
|
+
*/
|
|
1206
|
+
export type AttributeSet = Readonly<Record<string, string>>
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Utility type to extract the Input type from a Metric type.
|
|
1210
|
+
*
|
|
1211
|
+
* **Example** (Extracting metric input types)
|
|
1212
|
+
*
|
|
1213
|
+
* ```ts
|
|
1214
|
+
* import { Metric } from "effect"
|
|
1215
|
+
*
|
|
1216
|
+
* // Create various metric types
|
|
1217
|
+
* const numberCounter = Metric.counter("requests")
|
|
1218
|
+
* const bigintCounter = Metric.counter("bytes", { bigint: true })
|
|
1219
|
+
* const stringFrequency = Metric.frequency("status_codes")
|
|
1220
|
+
* const numberGauge = Metric.gauge("cpu_usage")
|
|
1221
|
+
* const numberHistogram = Metric.histogram("response_time", {
|
|
1222
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 10 })
|
|
1223
|
+
* })
|
|
1224
|
+
*
|
|
1225
|
+
* // The Input utility type extracts the input type from metric types:
|
|
1226
|
+
* // - Counter<number>: number
|
|
1227
|
+
* // - Counter<bigint>: bigint
|
|
1228
|
+
* // - Frequency: string
|
|
1229
|
+
* // - Gauge<number>: number
|
|
1230
|
+
* // - Histogram<number>: number
|
|
1231
|
+
*
|
|
1232
|
+
* // Helper function that works with any metric
|
|
1233
|
+
* const createMetricInfo = (metric: Metric.Metric<any, any>) => ({
|
|
1234
|
+
* id: metric.id,
|
|
1235
|
+
* type: metric.type
|
|
1236
|
+
* })
|
|
1237
|
+
*
|
|
1238
|
+
* const metrics = [
|
|
1239
|
+
* createMetricInfo(numberCounter), // { id: "requests", type: "Counter" }
|
|
1240
|
+
* createMetricInfo(bigintCounter), // { id: "bytes", type: "Counter" }
|
|
1241
|
+
* createMetricInfo(stringFrequency), // { id: "status_codes", type: "Frequency" }
|
|
1242
|
+
* createMetricInfo(numberGauge), // { id: "cpu_usage", type: "Gauge" }
|
|
1243
|
+
* createMetricInfo(numberHistogram) // { id: "response_time", type: "Histogram" }
|
|
1244
|
+
* ]
|
|
1245
|
+
*
|
|
1246
|
+
* // Type safety is enforced at compile time:
|
|
1247
|
+
* // Metric.update(numberCounter, 123) // ✓ Valid (number)
|
|
1248
|
+
* // Metric.update(numberCounter, "abc") // ✗ Type error
|
|
1249
|
+
* // Metric.update(stringFrequency, "ok") // ✓ Valid (string)
|
|
1250
|
+
* // Metric.update(stringFrequency, 404) // ✗ Type error
|
|
1251
|
+
* ```
|
|
1252
|
+
*
|
|
1253
|
+
* @category types
|
|
1254
|
+
* @since 4.0.0
|
|
1255
|
+
*/
|
|
1256
|
+
export type Input<A> = A extends Metric<infer _Input, infer _State> ? _Input
|
|
1257
|
+
: never
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* Utility type to extract the State type from a Metric type.
|
|
1261
|
+
*
|
|
1262
|
+
* **Example** (Extracting metric state types)
|
|
1263
|
+
*
|
|
1264
|
+
* ```ts
|
|
1265
|
+
* import { Effect, Metric } from "effect"
|
|
1266
|
+
*
|
|
1267
|
+
* // Create various metric types
|
|
1268
|
+
* const requestCounter = Metric.counter("requests")
|
|
1269
|
+
* const cpuGauge = Metric.gauge("cpu_usage")
|
|
1270
|
+
* const statusFrequency = Metric.frequency("status_codes")
|
|
1271
|
+
* const responseHistogram = Metric.histogram("response_time", {
|
|
1272
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 10 })
|
|
1273
|
+
* })
|
|
1274
|
+
* const latencySummary = Metric.summary("latency", {
|
|
1275
|
+
* maxAge: "5 minutes",
|
|
1276
|
+
* maxSize: 1000,
|
|
1277
|
+
* quantiles: [0.5, 0.95, 0.99]
|
|
1278
|
+
* })
|
|
1279
|
+
*
|
|
1280
|
+
* // The State utility type extracts the state type from metric types:
|
|
1281
|
+
* // - Counter<number>: CounterState<number>
|
|
1282
|
+
* // - Gauge<number>: GaugeState<number>
|
|
1283
|
+
* // - Frequency: FrequencyState
|
|
1284
|
+
* // - Histogram<number>: HistogramState
|
|
1285
|
+
* // - Summary<number>: SummaryState
|
|
1286
|
+
*
|
|
1287
|
+
* // Type-safe state analysis functions
|
|
1288
|
+
* const program = Effect.gen(function*() {
|
|
1289
|
+
* // Update metrics first
|
|
1290
|
+
* yield* Metric.update(requestCounter, 10)
|
|
1291
|
+
* yield* Metric.update(cpuGauge, 85.5)
|
|
1292
|
+
* yield* Metric.update(statusFrequency, "200")
|
|
1293
|
+
* yield* Metric.update(responseHistogram, 150)
|
|
1294
|
+
* yield* Metric.update(latencySummary, 120)
|
|
1295
|
+
*
|
|
1296
|
+
* // Extract states with proper typing
|
|
1297
|
+
* const counterState = yield* Metric.value(requestCounter)
|
|
1298
|
+
* const gaugeState = yield* Metric.value(cpuGauge)
|
|
1299
|
+
* const frequencyState = yield* Metric.value(statusFrequency)
|
|
1300
|
+
* const histogramState = yield* Metric.value(responseHistogram)
|
|
1301
|
+
* const summaryState = yield* Metric.value(latencySummary)
|
|
1302
|
+
*
|
|
1303
|
+
* return {
|
|
1304
|
+
* counter: { count: counterState.count }, // { count: 10 }
|
|
1305
|
+
* gauge: { value: gaugeState.value }, // { value: 85.5 }
|
|
1306
|
+
* frequency: { uniqueValues: frequencyState.occurrences.size }, // { uniqueValues: 1 }
|
|
1307
|
+
* histogram: { totalObservations: histogramState.count }, // { totalObservations: 1 }
|
|
1308
|
+
* summary: { observations: summaryState.count } // { observations: 1 }
|
|
1309
|
+
* }
|
|
1310
|
+
* })
|
|
1311
|
+
* ```
|
|
1312
|
+
*
|
|
1313
|
+
* @category types
|
|
1314
|
+
* @since 4.0.0
|
|
1315
|
+
*/
|
|
1316
|
+
export type State<A> = A extends Metric<infer _Input, infer _State> ? _State
|
|
1317
|
+
: never
|
|
1318
|
+
|
|
1319
|
+
/**
|
|
1320
|
+
* Interface defining the core hooks for metric operations: get, update, and modify.
|
|
1321
|
+
*
|
|
1322
|
+
* **Example** (Using metric hooks)
|
|
1323
|
+
*
|
|
1324
|
+
* ```ts
|
|
1325
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1326
|
+
*
|
|
1327
|
+
* class HooksError extends Data.TaggedError("HooksError")<{
|
|
1328
|
+
* readonly operation: string
|
|
1329
|
+
* }> {}
|
|
1330
|
+
*
|
|
1331
|
+
* const program = Effect.gen(function*() {
|
|
1332
|
+
* // Create a counter metric
|
|
1333
|
+
* const requestCounter = Metric.counter("requests_total", {
|
|
1334
|
+
* description: "Total number of requests"
|
|
1335
|
+
* })
|
|
1336
|
+
*
|
|
1337
|
+
* // The Hooks interface provides three core operations for metrics:
|
|
1338
|
+
* // 1. get: retrieve current state
|
|
1339
|
+
* // 2. update: add/set a value
|
|
1340
|
+
* // 3. modify: transform the current state
|
|
1341
|
+
*
|
|
1342
|
+
* // These are low-level APIs. Most users should use high-level APIs:
|
|
1343
|
+
* // - Metric.value() for getting state
|
|
1344
|
+
* // - Metric.update() for updating values
|
|
1345
|
+
* // - Metric.modify() for modifying values
|
|
1346
|
+
*
|
|
1347
|
+
* // Example using high-level APIs (recommended)
|
|
1348
|
+
* yield* Metric.update(requestCounter, 1)
|
|
1349
|
+
* yield* Metric.update(requestCounter, 5)
|
|
1350
|
+
* const state = yield* Metric.value(requestCounter)
|
|
1351
|
+
*
|
|
1352
|
+
* return {
|
|
1353
|
+
* currentCount: state.count, // 6
|
|
1354
|
+
* isIncremental: state.incremental // false
|
|
1355
|
+
* }
|
|
1356
|
+
* })
|
|
1357
|
+
* ```
|
|
1358
|
+
*
|
|
1359
|
+
* @category interfaces
|
|
1360
|
+
* @since 4.0.0
|
|
1361
|
+
*/
|
|
1362
|
+
export interface Hooks<in Input, out State> {
|
|
1363
|
+
readonly get: (context: Context.Context<never>) => State
|
|
1364
|
+
readonly update: (input: Input, context: Context.Context<never>) => void
|
|
1365
|
+
readonly modify: (input: Input, context: Context.Context<never>) => void
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Interface containing complete metadata information about a metric.
|
|
1370
|
+
*
|
|
1371
|
+
* **Example** (Inspecting metric metadata)
|
|
1372
|
+
*
|
|
1373
|
+
* ```ts
|
|
1374
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1375
|
+
*
|
|
1376
|
+
* class MetadataError extends Data.TaggedError("MetadataError")<{
|
|
1377
|
+
* readonly operation: string
|
|
1378
|
+
* }> {}
|
|
1379
|
+
*
|
|
1380
|
+
* const program = Effect.gen(function*() {
|
|
1381
|
+
* // Create metrics with different configurations
|
|
1382
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
1383
|
+
* description: "Total number of HTTP requests",
|
|
1384
|
+
* attributes: { service: "api", version: "1.0" }
|
|
1385
|
+
* })
|
|
1386
|
+
*
|
|
1387
|
+
* const memoryGauge = Metric.gauge("memory_usage_bytes", {
|
|
1388
|
+
* description: "Current memory usage in bytes"
|
|
1389
|
+
* })
|
|
1390
|
+
*
|
|
1391
|
+
* const statusFrequency = Metric.frequency("http_status_codes")
|
|
1392
|
+
*
|
|
1393
|
+
* // The Metadata interface contains complete information about a metric:
|
|
1394
|
+
* // - id: metric identifier
|
|
1395
|
+
* // - type: metric type ("Counter", "Gauge", etc.)
|
|
1396
|
+
* // - description: optional description
|
|
1397
|
+
* // - attributes: optional key-value attributes
|
|
1398
|
+
* // - hooks: low-level operations interface
|
|
1399
|
+
*
|
|
1400
|
+
* // Each metric has associated metadata that can be inspected
|
|
1401
|
+
* yield* Metric.update(requestCounter, 10)
|
|
1402
|
+
* yield* Metric.update(memoryGauge, 256000000)
|
|
1403
|
+
* yield* Metric.update(statusFrequency, "200")
|
|
1404
|
+
*
|
|
1405
|
+
* return {
|
|
1406
|
+
* counter: {
|
|
1407
|
+
* id: requestCounter.id, // "http_requests_total"
|
|
1408
|
+
* type: requestCounter.type, // "Counter"
|
|
1409
|
+
* description: requestCounter.description // "Total number of HTTP requests"
|
|
1410
|
+
* },
|
|
1411
|
+
* gauge: {
|
|
1412
|
+
* id: memoryGauge.id, // "memory_usage_bytes"
|
|
1413
|
+
* type: memoryGauge.type, // "Gauge"
|
|
1414
|
+
* description: memoryGauge.description // "Current memory usage in bytes"
|
|
1415
|
+
* },
|
|
1416
|
+
* frequency: {
|
|
1417
|
+
* id: statusFrequency.id, // "http_status_codes"
|
|
1418
|
+
* type: statusFrequency.type, // "Frequency"
|
|
1419
|
+
* description: statusFrequency.description // undefined
|
|
1420
|
+
* }
|
|
1421
|
+
* }
|
|
1422
|
+
* })
|
|
1423
|
+
* ```
|
|
1424
|
+
*
|
|
1425
|
+
* @category interfaces
|
|
1426
|
+
* @since 4.0.0
|
|
1427
|
+
*/
|
|
1428
|
+
export interface Metadata<in Input, out State> {
|
|
1429
|
+
readonly id: string
|
|
1430
|
+
readonly type: Type
|
|
1431
|
+
readonly description: string | undefined
|
|
1432
|
+
readonly attributes: Metric.AttributeSet | undefined
|
|
1433
|
+
readonly hooks: Hooks<Input, State>
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
/**
|
|
1437
|
+
* Protocol interface for metric snapshots containing metadata and current state.
|
|
1438
|
+
*
|
|
1439
|
+
* **Example** (Inspecting metric snapshot protocols)
|
|
1440
|
+
*
|
|
1441
|
+
* ```ts
|
|
1442
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1443
|
+
*
|
|
1444
|
+
* class SnapshotProtoError extends Data.TaggedError("SnapshotProtoError")<{
|
|
1445
|
+
* readonly operation: string
|
|
1446
|
+
* }> {}
|
|
1447
|
+
*
|
|
1448
|
+
* const program = Effect.gen(function*() {
|
|
1449
|
+
* // Create and update metrics
|
|
1450
|
+
* const requestCounter = Metric.counter("requests", {
|
|
1451
|
+
* description: "Request count",
|
|
1452
|
+
* attributes: { service: "api" }
|
|
1453
|
+
* })
|
|
1454
|
+
*
|
|
1455
|
+
* const responseTimeHistogram = Metric.histogram("response_time", {
|
|
1456
|
+
* description: "Response time distribution",
|
|
1457
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 10 })
|
|
1458
|
+
* })
|
|
1459
|
+
*
|
|
1460
|
+
* yield* Metric.update(requestCounter, 25)
|
|
1461
|
+
* yield* Metric.update(responseTimeHistogram, 150)
|
|
1462
|
+
* yield* Metric.update(responseTimeHistogram, 75)
|
|
1463
|
+
*
|
|
1464
|
+
* // Take snapshot of all metrics
|
|
1465
|
+
* const snapshots = yield* Metric.snapshot
|
|
1466
|
+
*
|
|
1467
|
+
* // Each snapshot follows the SnapshotProto interface:
|
|
1468
|
+
* // - id: metric identifier
|
|
1469
|
+
* // - type: specific metric type
|
|
1470
|
+
* // - description: optional description
|
|
1471
|
+
* // - attributes: optional attributes
|
|
1472
|
+
* // - state: current metric state
|
|
1473
|
+
*
|
|
1474
|
+
* const counterSnapshot = snapshots.find((s) => s.id === "requests")
|
|
1475
|
+
* const histogramSnapshot = snapshots.find((s) => s.id === "response_time")
|
|
1476
|
+
*
|
|
1477
|
+
* return {
|
|
1478
|
+
* counter: counterSnapshot ?
|
|
1479
|
+
* {
|
|
1480
|
+
* id: counterSnapshot.id, // "requests"
|
|
1481
|
+
* type: counterSnapshot.type, // "Counter"
|
|
1482
|
+
* description: counterSnapshot.description, // "Request count"
|
|
1483
|
+
* hasAttributes: counterSnapshot.attributes !== undefined, // true
|
|
1484
|
+
* count: (counterSnapshot.state as any).count // 25
|
|
1485
|
+
* } :
|
|
1486
|
+
* null,
|
|
1487
|
+
* histogram: histogramSnapshot ?
|
|
1488
|
+
* {
|
|
1489
|
+
* id: histogramSnapshot.id, // "response_time"
|
|
1490
|
+
* type: histogramSnapshot.type, // "Histogram"
|
|
1491
|
+
* observations: (histogramSnapshot.state as any).count // 2
|
|
1492
|
+
* } :
|
|
1493
|
+
* null
|
|
1494
|
+
* }
|
|
1495
|
+
* })
|
|
1496
|
+
* ```
|
|
1497
|
+
*
|
|
1498
|
+
* @category interfaces
|
|
1499
|
+
* @since 4.0.0
|
|
1500
|
+
*/
|
|
1501
|
+
export interface SnapshotProto<T extends Type, State> {
|
|
1502
|
+
readonly id: string
|
|
1503
|
+
readonly type: T
|
|
1504
|
+
readonly description: string | undefined
|
|
1505
|
+
readonly attributes: Metric.AttributeSet | undefined
|
|
1506
|
+
readonly state: State
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
/**
|
|
1510
|
+
* Union type representing all possible metric snapshot types with their corresponding states.
|
|
1511
|
+
*
|
|
1512
|
+
* **Example** (Analyzing metric snapshots)
|
|
1513
|
+
*
|
|
1514
|
+
* ```ts
|
|
1515
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1516
|
+
*
|
|
1517
|
+
* class SnapshotError extends Data.TaggedError("SnapshotError")<{
|
|
1518
|
+
* readonly operation: string
|
|
1519
|
+
* }> {}
|
|
1520
|
+
*
|
|
1521
|
+
* const program = Effect.gen(function*() {
|
|
1522
|
+
* // Create different types of metrics
|
|
1523
|
+
* const requestCounter = Metric.counter("requests_total")
|
|
1524
|
+
* const cpuGauge = Metric.gauge("cpu_usage_percent")
|
|
1525
|
+
* const statusFrequency = Metric.frequency("http_status")
|
|
1526
|
+
* const responseHistogram = Metric.histogram("response_time_ms", {
|
|
1527
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 100, count: 10 })
|
|
1528
|
+
* })
|
|
1529
|
+
* const latencySummary = Metric.summary("request_latency", {
|
|
1530
|
+
* maxAge: "1 minute",
|
|
1531
|
+
* maxSize: 100,
|
|
1532
|
+
* quantiles: [0.5, 0.95, 0.99]
|
|
1533
|
+
* })
|
|
1534
|
+
*
|
|
1535
|
+
* // Update all metrics
|
|
1536
|
+
* yield* Metric.update(requestCounter, 150)
|
|
1537
|
+
* yield* Metric.update(cpuGauge, 45.7)
|
|
1538
|
+
* yield* Metric.update(statusFrequency, "200")
|
|
1539
|
+
* yield* Metric.update(statusFrequency, "404")
|
|
1540
|
+
* yield* Metric.update(responseHistogram, 250)
|
|
1541
|
+
* yield* Metric.update(latencySummary, 120)
|
|
1542
|
+
*
|
|
1543
|
+
* // Take snapshot of all metrics
|
|
1544
|
+
* const allSnapshots = yield* Metric.snapshot
|
|
1545
|
+
*
|
|
1546
|
+
* // Type-safe snapshot analysis using discriminated union
|
|
1547
|
+
* const analyzeSnapshot = (snapshot: any) => {
|
|
1548
|
+
* switch (snapshot.type) {
|
|
1549
|
+
* case "Counter":
|
|
1550
|
+
* return { type: "Counter", count: snapshot.state.count }
|
|
1551
|
+
* case "Gauge":
|
|
1552
|
+
* return { type: "Gauge", value: snapshot.state.value }
|
|
1553
|
+
* case "Frequency":
|
|
1554
|
+
* return {
|
|
1555
|
+
* type: "Frequency",
|
|
1556
|
+
* uniqueValues: snapshot.state.occurrences.size
|
|
1557
|
+
* }
|
|
1558
|
+
* case "Histogram":
|
|
1559
|
+
* return { type: "Histogram", observations: snapshot.state.count }
|
|
1560
|
+
* case "Summary":
|
|
1561
|
+
* return { type: "Summary", observations: snapshot.state.count }
|
|
1562
|
+
* }
|
|
1563
|
+
* }
|
|
1564
|
+
*
|
|
1565
|
+
* const analysis = allSnapshots.map(analyzeSnapshot)
|
|
1566
|
+
*
|
|
1567
|
+
* return {
|
|
1568
|
+
* totalMetrics: allSnapshots.length, // 5
|
|
1569
|
+
* metricTypes: allSnapshots.map((s) => s.type), // ["Counter", "Gauge", "Frequency", "Histogram", "Summary"]
|
|
1570
|
+
* analysis
|
|
1571
|
+
* }
|
|
1572
|
+
* })
|
|
1573
|
+
* ```
|
|
1574
|
+
*
|
|
1575
|
+
* @category types
|
|
1576
|
+
* @since 4.0.0
|
|
1577
|
+
*/
|
|
1578
|
+
export type Snapshot =
|
|
1579
|
+
| SnapshotProto<"Counter", CounterState<number | bigint>>
|
|
1580
|
+
| SnapshotProto<"Gauge", GaugeState<number | bigint>>
|
|
1581
|
+
| SnapshotProto<"Frequency", FrequencyState>
|
|
1582
|
+
| SnapshotProto<"Histogram", HistogramState>
|
|
1583
|
+
| SnapshotProto<"Summary", SummaryState>
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
/**
|
|
1587
|
+
* Service key for the current metric attributes context.
|
|
1588
|
+
*
|
|
1589
|
+
* **Example** (Accessing the current metric attributes key)
|
|
1590
|
+
*
|
|
1591
|
+
* ```ts
|
|
1592
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1593
|
+
*
|
|
1594
|
+
* class AttributesKeyError extends Data.TaggedError("AttributesKeyError")<{
|
|
1595
|
+
* readonly operation: string
|
|
1596
|
+
* }> {}
|
|
1597
|
+
*
|
|
1598
|
+
* const program = Effect.gen(function*() {
|
|
1599
|
+
* // The key is used internally by the Effect runtime to manage metric attributes
|
|
1600
|
+
* const key = Metric.CurrentMetricAttributesKey
|
|
1601
|
+
*
|
|
1602
|
+
* // Create metrics with base attributes
|
|
1603
|
+
* const requestCounter = Metric.counter("requests_total", {
|
|
1604
|
+
* description: "Total HTTP requests"
|
|
1605
|
+
* })
|
|
1606
|
+
*
|
|
1607
|
+
* // The CurrentMetricAttributes service provides default attributes
|
|
1608
|
+
* // that get applied to all metrics in the current context
|
|
1609
|
+
* const baseAttributes = { service: "api", version: "1.0" }
|
|
1610
|
+
*
|
|
1611
|
+
* // Use withAttributes to apply attributes to metrics
|
|
1612
|
+
* const taggedCounter1 = Metric.withAttributes(requestCounter, baseAttributes)
|
|
1613
|
+
* const program1 = Metric.update(taggedCounter1, 1)
|
|
1614
|
+
*
|
|
1615
|
+
* const taggedCounter2 = Metric.withAttributes(requestCounter, {
|
|
1616
|
+
* ...baseAttributes,
|
|
1617
|
+
* endpoint: "/users"
|
|
1618
|
+
* })
|
|
1619
|
+
* const program2 = Metric.update(taggedCounter2, 5)
|
|
1620
|
+
*
|
|
1621
|
+
* yield* program1
|
|
1622
|
+
* yield* program2
|
|
1623
|
+
*
|
|
1624
|
+
* return {
|
|
1625
|
+
* keyValue: key, // "effect/Metric/CurrentMetricAttributes"
|
|
1626
|
+
* keyType: typeof key, // "string"
|
|
1627
|
+
* isConstant: key === "effect/Metric/CurrentMetricAttributes" // true
|
|
1628
|
+
* }
|
|
1629
|
+
* })
|
|
1630
|
+
* ```
|
|
1631
|
+
*
|
|
1632
|
+
* @category references
|
|
1633
|
+
* @since 4.0.0
|
|
1634
|
+
*/
|
|
1635
|
+
export const CurrentMetricAttributesKey = "effect/Metric/CurrentMetricAttributes" as const
|
|
1636
|
+
|
|
1637
|
+
/**
|
|
1638
|
+
* Context reference for metric attributes applied from the current Effect
|
|
1639
|
+
* context.
|
|
1640
|
+
*
|
|
1641
|
+
* **When to use**
|
|
1642
|
+
*
|
|
1643
|
+
* Use to provide default attributes that should be merged into metric updates
|
|
1644
|
+
* and reads in a scoped part of a program.
|
|
1645
|
+
*
|
|
1646
|
+
* **Details**
|
|
1647
|
+
*
|
|
1648
|
+
* The default value is an empty attribute set. Metric reads and updates merge
|
|
1649
|
+
* these contextual attributes with the metric's own attributes to select the
|
|
1650
|
+
* metric series being accessed.
|
|
1651
|
+
*
|
|
1652
|
+
* **Example** (Providing current metric attributes)
|
|
1653
|
+
*
|
|
1654
|
+
* ```ts
|
|
1655
|
+
* import { Data, Effect, Metric } from "effect"
|
|
1656
|
+
*
|
|
1657
|
+
* class AttributesError extends Data.TaggedError("AttributesError")<{
|
|
1658
|
+
* readonly operation: string
|
|
1659
|
+
* }> {}
|
|
1660
|
+
*
|
|
1661
|
+
* const program = Effect.gen(function*() {
|
|
1662
|
+
* // Access current metric attributes
|
|
1663
|
+
* const attributes = yield* Metric.CurrentMetricAttributes
|
|
1664
|
+
* console.log("Current attributes:", attributes)
|
|
1665
|
+
*
|
|
1666
|
+
* // Set new attributes context
|
|
1667
|
+
* const newAttributes = { service: "api", version: "1.0" }
|
|
1668
|
+
* const result = yield* Effect.provideService(
|
|
1669
|
+
* Effect.gen(function*() {
|
|
1670
|
+
* const updatedAttributes = yield* Metric.CurrentMetricAttributes
|
|
1671
|
+
* return updatedAttributes
|
|
1672
|
+
* }),
|
|
1673
|
+
* Metric.CurrentMetricAttributes,
|
|
1674
|
+
* newAttributes
|
|
1675
|
+
* )
|
|
1676
|
+
*
|
|
1677
|
+
* return result
|
|
1678
|
+
* })
|
|
1679
|
+
* ```
|
|
1680
|
+
*
|
|
1681
|
+
* @category references
|
|
1682
|
+
* @since 4.0.0
|
|
1683
|
+
*/
|
|
1684
|
+
export const CurrentMetricAttributes = Context.Reference<Metric.AttributeSet>(CurrentMetricAttributesKey, {
|
|
1685
|
+
defaultValue: () => ({})
|
|
1686
|
+
})
|
|
1687
|
+
|
|
1688
|
+
const MetricRegistryKey = "~effect/observability/Metric/MetricRegistryKey"
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* Context reference for the metric registry in the current context.
|
|
1692
|
+
*
|
|
1693
|
+
* **When to use**
|
|
1694
|
+
*
|
|
1695
|
+
* Use when you need a custom metric registry for an isolated program or test
|
|
1696
|
+
* instead of the default registry.
|
|
1697
|
+
*
|
|
1698
|
+
* **Details**
|
|
1699
|
+
*
|
|
1700
|
+
* By default, the reference creates an empty `Map` the first time it is
|
|
1701
|
+
* resolved. Metrics register their metadata and hooks lazily in this map when
|
|
1702
|
+
* they are read or updated.
|
|
1703
|
+
*
|
|
1704
|
+
* **Gotchas**
|
|
1705
|
+
*
|
|
1706
|
+
* Because `Context.Reference` caches default values, the default `Map` is
|
|
1707
|
+
* shared by contexts that do not provide an override. Provide `MetricRegistry`
|
|
1708
|
+
* with a fresh `Map` when isolation matters.
|
|
1709
|
+
*
|
|
1710
|
+
* @see {@link snapshot} for reading all registered metrics from the current `Effect` context
|
|
1711
|
+
* @see {@link snapshotUnsafe} for reading all registered metrics from an explicit `Context`
|
|
1712
|
+
*
|
|
1713
|
+
* @category references
|
|
1714
|
+
* @since 4.0.0
|
|
1715
|
+
*/
|
|
1716
|
+
export const MetricRegistry = Context.Reference<Map<string, Metric.Metadata<any, any>>>(
|
|
1717
|
+
MetricRegistryKey,
|
|
1718
|
+
{ defaultValue: () => new Map() }
|
|
1719
|
+
)
|
|
1720
|
+
|
|
1721
|
+
const TypeId = "~effect/observability/Metric"
|
|
1722
|
+
|
|
1723
|
+
abstract class Metric$<in Input, out State> implements Metric<Input, State> {
|
|
1724
|
+
readonly [TypeId] = TypeId
|
|
1725
|
+
|
|
1726
|
+
abstract readonly type: Metric.Type
|
|
1727
|
+
|
|
1728
|
+
declare readonly Input: Contravariant<Input>
|
|
1729
|
+
declare readonly State: Covariant<State>
|
|
1730
|
+
|
|
1731
|
+
readonly #metadataCache = new WeakMap<Metric.Attributes, Metric.Metadata<Input, State>>()
|
|
1732
|
+
#metadata: Metric.Metadata<Input, State> | undefined
|
|
1733
|
+
|
|
1734
|
+
readonly id: string
|
|
1735
|
+
readonly description: string | undefined
|
|
1736
|
+
readonly attributes: Metric.AttributeSet | undefined
|
|
1737
|
+
|
|
1738
|
+
constructor(
|
|
1739
|
+
id: string,
|
|
1740
|
+
description: string | undefined,
|
|
1741
|
+
attributes: Metric.AttributeSet | undefined
|
|
1742
|
+
) {
|
|
1743
|
+
this.id = id
|
|
1744
|
+
this.description = description
|
|
1745
|
+
this.attributes = attributes
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
valueUnsafe(context: Context.Context<never>): State {
|
|
1749
|
+
return this.hook(context).get(context)
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
modifyUnsafe(input: Input, context: Context.Context<never>): void {
|
|
1753
|
+
return this.hook(context).modify(input, context)
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
updateUnsafe(input: Input, context: Context.Context<never>): void {
|
|
1757
|
+
return this.hook(context).update(input, context)
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
abstract createHooks(): Metric.Hooks<Input, State>
|
|
1761
|
+
|
|
1762
|
+
hook(context: Context.Context<never>): Metric.Hooks<Input, State> {
|
|
1763
|
+
const extraAttributes = Context.get(context, CurrentMetricAttributes)
|
|
1764
|
+
if (Object.keys(extraAttributes).length === 0) {
|
|
1765
|
+
if (Predicate.isNotUndefined(this.#metadata)) {
|
|
1766
|
+
return this.#metadata.hooks
|
|
1767
|
+
}
|
|
1768
|
+
this.#metadata = this.getOrCreate(context, this.attributes)
|
|
1769
|
+
return this.#metadata.hooks
|
|
1770
|
+
}
|
|
1771
|
+
const mergedAttributes = mergeAttributes(this.attributes, extraAttributes)
|
|
1772
|
+
let metadata = this.#metadataCache.get(mergedAttributes)
|
|
1773
|
+
if (Predicate.isNotUndefined(metadata)) {
|
|
1774
|
+
return metadata.hooks
|
|
1775
|
+
}
|
|
1776
|
+
metadata = this.getOrCreate(context, mergedAttributes)
|
|
1777
|
+
this.#metadataCache.set(mergedAttributes, metadata)
|
|
1778
|
+
return metadata.hooks
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
getOrCreate(
|
|
1782
|
+
context: Context.Context<never>,
|
|
1783
|
+
attributes: Metric.Attributes | undefined
|
|
1784
|
+
): Metric.Metadata<Input, State> {
|
|
1785
|
+
const key = makeKey(this, attributes)
|
|
1786
|
+
const registry = Context.get(context, MetricRegistry)
|
|
1787
|
+
if (registry.has(key)) {
|
|
1788
|
+
return registry.get(key)!
|
|
1789
|
+
}
|
|
1790
|
+
const hooks = this.createHooks()
|
|
1791
|
+
const meta: Metric.Metadata<Input, State> = {
|
|
1792
|
+
id: this.id,
|
|
1793
|
+
type: this.type,
|
|
1794
|
+
description: this.description,
|
|
1795
|
+
attributes: attributesToRecord(attributes),
|
|
1796
|
+
hooks
|
|
1797
|
+
}
|
|
1798
|
+
registry.set(key, meta)
|
|
1799
|
+
return meta
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
pipe() {
|
|
1803
|
+
return pipeArguments(this, arguments)
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
const bigint0 = BigInt(0)
|
|
1808
|
+
|
|
1809
|
+
class CounterMetric<Input extends number | bigint> extends Metric$<Input, CounterState<Input>> {
|
|
1810
|
+
readonly type = "Counter"
|
|
1811
|
+
readonly #bigint: boolean
|
|
1812
|
+
readonly #incremental: boolean
|
|
1813
|
+
|
|
1814
|
+
constructor(id: string, options?: {
|
|
1815
|
+
readonly description?: string | undefined
|
|
1816
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
1817
|
+
readonly bigint?: boolean | undefined
|
|
1818
|
+
readonly incremental?: boolean | undefined
|
|
1819
|
+
}) {
|
|
1820
|
+
super(id, options?.description, attributesToRecord(options?.attributes))
|
|
1821
|
+
this.#bigint = options?.bigint ?? false
|
|
1822
|
+
this.#incremental = options?.incremental ?? false
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
createHooks(): Metric.Hooks<Input, CounterState<Input>> {
|
|
1826
|
+
let count = (this.#bigint ? bigint0 : 0) as any
|
|
1827
|
+
const canUpdate = this.#incremental
|
|
1828
|
+
? this.#bigint
|
|
1829
|
+
? (value: bigint | number) => value >= bigint0
|
|
1830
|
+
: (value: bigint | number) => value >= 0
|
|
1831
|
+
: (_value: bigint | number) => true
|
|
1832
|
+
const update = (value: Input) => {
|
|
1833
|
+
if (canUpdate(value)) {
|
|
1834
|
+
count = (count as any) + value
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
return makeHooks(() => ({ count, incremental: this.#incremental }), update)
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
class GaugeMetric<Input extends number | bigint> extends Metric$<Input, GaugeState<Input>> {
|
|
1842
|
+
readonly type = "Gauge"
|
|
1843
|
+
readonly #bigint: boolean
|
|
1844
|
+
|
|
1845
|
+
constructor(id: string, options?: {
|
|
1846
|
+
readonly description?: string | undefined
|
|
1847
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
1848
|
+
readonly bigint?: boolean | undefined
|
|
1849
|
+
}) {
|
|
1850
|
+
super(id, options?.description, attributesToRecord(options?.attributes))
|
|
1851
|
+
this.#bigint = options?.bigint ?? false
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
createHooks(): Metric.Hooks<Input, GaugeState<Input>> {
|
|
1855
|
+
let value = this.#bigint ? BigInt(0) as any : 0
|
|
1856
|
+
const update = (input: number | bigint) => {
|
|
1857
|
+
value = input
|
|
1858
|
+
}
|
|
1859
|
+
const modify = (input: number | bigint) => {
|
|
1860
|
+
value = value + input
|
|
1861
|
+
}
|
|
1862
|
+
return makeHooks(() => ({ value }), update, modify)
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
class FrequencyMetric extends Metric$<string, FrequencyState> {
|
|
1867
|
+
readonly type = "Frequency"
|
|
1868
|
+
readonly #preregisteredWords: ReadonlyArray<string> | undefined
|
|
1869
|
+
|
|
1870
|
+
constructor(id: string, options?: {
|
|
1871
|
+
readonly description?: string | undefined
|
|
1872
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
1873
|
+
readonly preregisteredWords?: ReadonlyArray<string> | undefined
|
|
1874
|
+
}) {
|
|
1875
|
+
super(id, options?.description, attributesToRecord(options?.attributes))
|
|
1876
|
+
this.#preregisteredWords = options?.preregisteredWords
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
createHooks(): Metric.Hooks<string, FrequencyState> {
|
|
1880
|
+
const occurrences = new Map<string, number>()
|
|
1881
|
+
if (Predicate.isNotUndefined(this.#preregisteredWords)) {
|
|
1882
|
+
for (const word of this.#preregisteredWords) {
|
|
1883
|
+
occurrences.set(word, 0)
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
const update = (word: string) => {
|
|
1887
|
+
const count = occurrences.get(word) ?? 0
|
|
1888
|
+
occurrences.set(word, count + 1)
|
|
1889
|
+
}
|
|
1890
|
+
return makeHooks(() => ({ occurrences }), update)
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
class HistogramMetric extends Metric$<number, HistogramState> {
|
|
1895
|
+
readonly type = "Histogram"
|
|
1896
|
+
readonly #boundaries: ReadonlyArray<number>
|
|
1897
|
+
|
|
1898
|
+
constructor(id: string, options: {
|
|
1899
|
+
readonly description?: string | undefined
|
|
1900
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
1901
|
+
readonly boundaries: ReadonlyArray<number>
|
|
1902
|
+
}) {
|
|
1903
|
+
super(id, options?.description, attributesToRecord(options?.attributes))
|
|
1904
|
+
this.#boundaries = options.boundaries
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
createHooks(): Metric.Hooks<number, HistogramState> {
|
|
1908
|
+
const bounds = this.#boundaries
|
|
1909
|
+
const size = bounds.length
|
|
1910
|
+
const values = new Uint32Array(size + 1)
|
|
1911
|
+
const boundaries = new Float64Array(size)
|
|
1912
|
+
let count = 0
|
|
1913
|
+
let sum = 0
|
|
1914
|
+
let min = Number.MAX_VALUE
|
|
1915
|
+
let max = Number.MIN_VALUE
|
|
1916
|
+
|
|
1917
|
+
Arr.map(Arr.sort(bounds, Order.Number), (n, i) => {
|
|
1918
|
+
boundaries[i] = n
|
|
1919
|
+
})
|
|
1920
|
+
|
|
1921
|
+
// Insert the value into the right bucket with a binary search
|
|
1922
|
+
const update = (value: number) => {
|
|
1923
|
+
let from = 0
|
|
1924
|
+
let to = size
|
|
1925
|
+
while (from !== to) {
|
|
1926
|
+
const mid = Math.floor(from + (to - from) / 2)
|
|
1927
|
+
const boundary = boundaries[mid]
|
|
1928
|
+
if (value <= boundary) {
|
|
1929
|
+
to = mid
|
|
1930
|
+
} else {
|
|
1931
|
+
from = mid
|
|
1932
|
+
}
|
|
1933
|
+
// The special case when to / from have a distance of one
|
|
1934
|
+
if (to === from + 1) {
|
|
1935
|
+
if (value <= boundaries[from]) {
|
|
1936
|
+
to = from
|
|
1937
|
+
} else {
|
|
1938
|
+
from = to
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
values[from] = values[from] + 1
|
|
1943
|
+
count = count + 1
|
|
1944
|
+
sum = sum + value
|
|
1945
|
+
if (value < min) {
|
|
1946
|
+
min = value
|
|
1947
|
+
}
|
|
1948
|
+
if (value > max) {
|
|
1949
|
+
max = value
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
const getBuckets = (): ReadonlyArray<[number, number]> => {
|
|
1954
|
+
const builder: Array<[number, number]> = Arr.allocate(size) as any
|
|
1955
|
+
let cumulated = 0
|
|
1956
|
+
for (let i = 0; i < size; i++) {
|
|
1957
|
+
const boundary = boundaries[i]
|
|
1958
|
+
const value = values[i]
|
|
1959
|
+
cumulated = cumulated + value
|
|
1960
|
+
builder[i] = [boundary, cumulated]
|
|
1961
|
+
}
|
|
1962
|
+
return builder
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
return makeHooks(() => ({ buckets: getBuckets(), count, min, max, sum }), update)
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
class SummaryMetric extends Metric$<readonly [value: number, timestamp: number], SummaryState> {
|
|
1970
|
+
readonly type = "Summary"
|
|
1971
|
+
readonly #maxAge: number
|
|
1972
|
+
readonly #maxSize: number
|
|
1973
|
+
readonly #quantiles: ReadonlyArray<number>
|
|
1974
|
+
|
|
1975
|
+
constructor(id: string, options: {
|
|
1976
|
+
readonly description?: string | undefined
|
|
1977
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
1978
|
+
readonly maxAge: Duration.Input
|
|
1979
|
+
readonly maxSize: number
|
|
1980
|
+
readonly quantiles: ReadonlyArray<number>
|
|
1981
|
+
}) {
|
|
1982
|
+
super(id, options?.description, attributesToRecord(options?.attributes))
|
|
1983
|
+
this.#maxAge = Math.max(Duration.toMillis(Duration.fromInputUnsafe(options.maxAge)), 0)
|
|
1984
|
+
this.#maxSize = options.maxSize
|
|
1985
|
+
this.#quantiles = options.quantiles
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
createHooks(): Metric.Hooks<readonly [value: number, timestamp: number], SummaryState> {
|
|
1989
|
+
const sortedQuantiles = Arr.sort(this.#quantiles, Order.Number)
|
|
1990
|
+
const observations = Arr.allocate<[number, number]>(this.#maxSize)
|
|
1991
|
+
|
|
1992
|
+
for (const quantile of this.#quantiles) {
|
|
1993
|
+
if (quantile < 0 || quantile > 1) {
|
|
1994
|
+
throw new Error(`Quantile must be between 0 and 1, found: ${quantile}`)
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
let head = 0
|
|
1999
|
+
let count = 0
|
|
2000
|
+
let sum = 0
|
|
2001
|
+
let min = Number.MAX_VALUE
|
|
2002
|
+
let max = Number.MIN_VALUE
|
|
2003
|
+
|
|
2004
|
+
const snapshot = (now: number): ReadonlyArray<[number, number | undefined]> => {
|
|
2005
|
+
const builder: Array<number> = []
|
|
2006
|
+
let i = 0
|
|
2007
|
+
while (i < this.#maxSize) {
|
|
2008
|
+
const observation = observations[i]
|
|
2009
|
+
if (Predicate.isNotUndefined(observation)) {
|
|
2010
|
+
const [timestamp, value] = observation
|
|
2011
|
+
const age = now - timestamp
|
|
2012
|
+
if (age >= 0 && age <= this.#maxAge) {
|
|
2013
|
+
builder.push(value)
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
i = i + 1
|
|
2017
|
+
}
|
|
2018
|
+
const samples = Arr.sort(builder, Order.Number)
|
|
2019
|
+
const sampleSize = samples.length
|
|
2020
|
+
if (sampleSize === 0) {
|
|
2021
|
+
return sortedQuantiles.map((q) => [q, undefined])
|
|
2022
|
+
}
|
|
2023
|
+
// Compute the value of the quantile in terms of rank:
|
|
2024
|
+
// > For a given quantile `q`, return the maximum value `v` such that at
|
|
2025
|
+
// > most `q * n` values are less than or equal to `v`.
|
|
2026
|
+
return sortedQuantiles.map((q) => {
|
|
2027
|
+
if (q <= 0) return [q, samples[0]]
|
|
2028
|
+
if (q >= 1) return [q, samples[sampleSize - 1]]
|
|
2029
|
+
const index = Math.ceil(q * sampleSize) - 1
|
|
2030
|
+
return [q, samples[index]]
|
|
2031
|
+
})
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
const observe = (value: number, timestamp: number) => {
|
|
2035
|
+
if (this.#maxSize > 0) {
|
|
2036
|
+
const target = head % this.#maxSize
|
|
2037
|
+
observations[target] = [timestamp, value] as const
|
|
2038
|
+
head = head + 1
|
|
2039
|
+
}
|
|
2040
|
+
count = count + 1
|
|
2041
|
+
sum = sum + value
|
|
2042
|
+
if (value < min) {
|
|
2043
|
+
min = value
|
|
2044
|
+
}
|
|
2045
|
+
if (value > max) {
|
|
2046
|
+
max = value
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
const get = (context: Context.Context<never>) => {
|
|
2051
|
+
const clock = Context.get(context, InternalEffect.ClockRef)
|
|
2052
|
+
const quantiles = snapshot(clock.currentTimeMillisUnsafe())
|
|
2053
|
+
return { quantiles, count, min, max, sum }
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
const update = ([value, timestamp]: readonly [value: number, timestamp: number]) => observe(value, timestamp)
|
|
2057
|
+
|
|
2058
|
+
return makeHooks(get, update)
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
class MetricTransform<in Input, out State, in Input2> extends Metric$<Input2, State> {
|
|
2063
|
+
type: Metric.Type
|
|
2064
|
+
readonly metric: Metric<Input, State>
|
|
2065
|
+
override readonly valueUnsafe: (context: Context.Context<never>) => State
|
|
2066
|
+
override readonly updateUnsafe: (input: Input2, context: Context.Context<never>) => void
|
|
2067
|
+
override readonly modifyUnsafe: (input: Input2, context: Context.Context<never>) => void
|
|
2068
|
+
|
|
2069
|
+
constructor(
|
|
2070
|
+
metric: Metric<Input, State>,
|
|
2071
|
+
valueUnsafe: (context: Context.Context<never>) => State,
|
|
2072
|
+
updateUnsafe: (input: Input2, context: Context.Context<never>) => void,
|
|
2073
|
+
modifyUnsafe: (input: Input2, context: Context.Context<never>) => void
|
|
2074
|
+
) {
|
|
2075
|
+
super(metric.id, metric.description, metric.attributes)
|
|
2076
|
+
this.metric = metric
|
|
2077
|
+
this.valueUnsafe = valueUnsafe
|
|
2078
|
+
this.updateUnsafe = updateUnsafe
|
|
2079
|
+
this.modifyUnsafe = modifyUnsafe
|
|
2080
|
+
this.type = metric.type
|
|
2081
|
+
}
|
|
2082
|
+
createHooks(): Metric.Hooks<Input2, State> {
|
|
2083
|
+
return (this.metric as any).createHooks()
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
/**
|
|
2088
|
+
* Returns `true` if the specified value is a `Metric`, otherwise returns `false`.
|
|
2089
|
+
*
|
|
2090
|
+
* **When to use**
|
|
2091
|
+
*
|
|
2092
|
+
* Use when you need runtime type checking and ensuring that a value
|
|
2093
|
+
* conforms to the Metric interface before performing metric operations.
|
|
2094
|
+
*
|
|
2095
|
+
* **Example** (Checking metric values)
|
|
2096
|
+
*
|
|
2097
|
+
* ```ts
|
|
2098
|
+
* import { Metric } from "effect"
|
|
2099
|
+
*
|
|
2100
|
+
* const counter = Metric.counter("requests")
|
|
2101
|
+
* const gauge = Metric.gauge("temperature")
|
|
2102
|
+
* const notAMetric = { name: "fake-metric" }
|
|
2103
|
+
*
|
|
2104
|
+
* console.log(Metric.isMetric(counter)) // true
|
|
2105
|
+
* console.log(Metric.isMetric(gauge)) // true
|
|
2106
|
+
* console.log(Metric.isMetric(notAMetric)) // false
|
|
2107
|
+
* console.log(Metric.isMetric(null)) // false
|
|
2108
|
+
* ```
|
|
2109
|
+
*
|
|
2110
|
+
* @category guards
|
|
2111
|
+
* @since 4.0.0
|
|
2112
|
+
*/
|
|
2113
|
+
export const isMetric = (u: unknown): u is Metric<unknown, never> =>
|
|
2114
|
+
Predicate.hasProperty(u, "~effect/Metric") && u["~effect/Metric"] === "~effect/Metric"
|
|
2115
|
+
|
|
2116
|
+
/**
|
|
2117
|
+
* Represents a Counter metric that tracks cumulative numerical values over
|
|
2118
|
+
* time. Counters can be incremented and decremented and provide a running total
|
|
2119
|
+
* of changes.
|
|
2120
|
+
*
|
|
2121
|
+
* **Details**
|
|
2122
|
+
*
|
|
2123
|
+
* The optional `description` describes the counter, and `attributes` attach
|
|
2124
|
+
* dimensions to it. Set `bigint` to create a counter that accepts `bigint`
|
|
2125
|
+
* inputs. Set `incremental` to `true` to create a counter that can only ever be
|
|
2126
|
+
* incremented.
|
|
2127
|
+
*
|
|
2128
|
+
* **Example** (Creating counter metrics)
|
|
2129
|
+
*
|
|
2130
|
+
* ```ts
|
|
2131
|
+
* import { Data, Effect, Metric } from "effect"
|
|
2132
|
+
*
|
|
2133
|
+
* class CounterError extends Data.TaggedError("CounterError")<{
|
|
2134
|
+
* readonly operation: string
|
|
2135
|
+
* }> {}
|
|
2136
|
+
*
|
|
2137
|
+
* const program = Effect.gen(function*() {
|
|
2138
|
+
* // Create a basic counter for tracking requests
|
|
2139
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
2140
|
+
* description: "Total number of HTTP requests processed"
|
|
2141
|
+
* })
|
|
2142
|
+
*
|
|
2143
|
+
* // Create an incremental-only counter for events
|
|
2144
|
+
* const eventCounter = Metric.counter("events_processed", {
|
|
2145
|
+
* description: "Events processed (increment only)",
|
|
2146
|
+
* incremental: true
|
|
2147
|
+
* })
|
|
2148
|
+
*
|
|
2149
|
+
* // Create a bigint counter for large values
|
|
2150
|
+
* const bytesCounter = Metric.counter("bytes_transferred", {
|
|
2151
|
+
* description: "Total bytes transferred",
|
|
2152
|
+
* bigint: true,
|
|
2153
|
+
* attributes: { service: "file-transfer" }
|
|
2154
|
+
* })
|
|
2155
|
+
*
|
|
2156
|
+
* // Update counters with values
|
|
2157
|
+
* yield* Metric.update(requestCounter, 1) // Increment by 1
|
|
2158
|
+
* yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
|
|
2159
|
+
* yield* Metric.update(eventCounter, 1) // Increment by 1
|
|
2160
|
+
* yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
|
|
2161
|
+
*
|
|
2162
|
+
* // Get current counter values
|
|
2163
|
+
* const requestValue = yield* Metric.value(requestCounter)
|
|
2164
|
+
* const eventValue = yield* Metric.value(eventCounter)
|
|
2165
|
+
* const bytesValue = yield* Metric.value(bytesCounter)
|
|
2166
|
+
*
|
|
2167
|
+
* return { requestValue, eventValue, bytesValue }
|
|
2168
|
+
* })
|
|
2169
|
+
* ```
|
|
2170
|
+
*
|
|
2171
|
+
* @category constructors
|
|
2172
|
+
* @since 2.0.0
|
|
2173
|
+
*/
|
|
2174
|
+
export const counter: {
|
|
2175
|
+
(
|
|
2176
|
+
name: string,
|
|
2177
|
+
options?: {
|
|
2178
|
+
readonly description?: string | undefined
|
|
2179
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2180
|
+
readonly bigint?: false | undefined
|
|
2181
|
+
readonly incremental?: boolean | undefined
|
|
2182
|
+
}
|
|
2183
|
+
): Counter<number>
|
|
2184
|
+
(
|
|
2185
|
+
name: string,
|
|
2186
|
+
options: {
|
|
2187
|
+
readonly description?: string | undefined
|
|
2188
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2189
|
+
readonly bigint: true
|
|
2190
|
+
readonly incremental?: boolean | undefined
|
|
2191
|
+
}
|
|
2192
|
+
): Counter<bigint>
|
|
2193
|
+
} = (name, options) => new CounterMetric(name, options) as any
|
|
2194
|
+
|
|
2195
|
+
/**
|
|
2196
|
+
* Represents a `Gauge` metric that tracks and reports a single numerical value
|
|
2197
|
+
* at a specific moment.
|
|
2198
|
+
*
|
|
2199
|
+
* **When to use**
|
|
2200
|
+
*
|
|
2201
|
+
* Use when you need a metric for instantaneous values, such as memory usage or
|
|
2202
|
+
* CPU load.
|
|
2203
|
+
*
|
|
2204
|
+
* **Details**
|
|
2205
|
+
*
|
|
2206
|
+
* The optional `description` describes the gauge, and `attributes` attach
|
|
2207
|
+
* dimensions to it. Set `bigint` to create a gauge that accepts `bigint`
|
|
2208
|
+
* inputs.
|
|
2209
|
+
*
|
|
2210
|
+
* **Example** (Creating gauge metrics)
|
|
2211
|
+
*
|
|
2212
|
+
* ```ts
|
|
2213
|
+
* import { Data, Effect, Metric } from "effect"
|
|
2214
|
+
*
|
|
2215
|
+
* class GaugeError extends Data.TaggedError("GaugeError")<{
|
|
2216
|
+
* readonly operation: string
|
|
2217
|
+
* }> {}
|
|
2218
|
+
*
|
|
2219
|
+
* const program = Effect.gen(function*() {
|
|
2220
|
+
* // Create a gauge for tracking memory usage
|
|
2221
|
+
* const memoryGauge = Metric.gauge("memory_usage_mb", {
|
|
2222
|
+
* description: "Current memory usage in megabytes"
|
|
2223
|
+
* })
|
|
2224
|
+
*
|
|
2225
|
+
* // Create a gauge for CPU utilization
|
|
2226
|
+
* const cpuGauge = Metric.gauge("cpu_utilization", {
|
|
2227
|
+
* description: "Current CPU utilization percentage",
|
|
2228
|
+
* attributes: { host: "server-01" }
|
|
2229
|
+
* })
|
|
2230
|
+
*
|
|
2231
|
+
* // Create a bigint gauge for large values
|
|
2232
|
+
* const diskSpaceGauge = Metric.gauge("disk_free_bytes", {
|
|
2233
|
+
* description: "Free disk space in bytes",
|
|
2234
|
+
* bigint: true
|
|
2235
|
+
* })
|
|
2236
|
+
*
|
|
2237
|
+
* // Set gauge values (replaces current value)
|
|
2238
|
+
* yield* Metric.update(memoryGauge, 512) // Set to 512 MB
|
|
2239
|
+
* yield* Metric.update(cpuGauge, 85.5) // Set to 85.5%
|
|
2240
|
+
* yield* Metric.update(diskSpaceGauge, 1024000000n) // Set to ~1GB
|
|
2241
|
+
*
|
|
2242
|
+
* // Modify gauge values (adds to current value)
|
|
2243
|
+
* yield* Metric.modify(memoryGauge, 128) // Increase by 128 MB (total: 640)
|
|
2244
|
+
* yield* Metric.modify(cpuGauge, -10.5) // Decrease by 10.5% (total: 75%)
|
|
2245
|
+
*
|
|
2246
|
+
* // Update with new absolute values
|
|
2247
|
+
* yield* Metric.update(memoryGauge, 800) // Set to 800 MB (replaces 640)
|
|
2248
|
+
*
|
|
2249
|
+
* // Get current gauge values
|
|
2250
|
+
* const memoryValue = yield* Metric.value(memoryGauge)
|
|
2251
|
+
* const cpuValue = yield* Metric.value(cpuGauge)
|
|
2252
|
+
* const diskValue = yield* Metric.value(diskSpaceGauge)
|
|
2253
|
+
*
|
|
2254
|
+
* return { memoryValue, cpuValue, diskValue }
|
|
2255
|
+
* })
|
|
2256
|
+
* ```
|
|
2257
|
+
*
|
|
2258
|
+
* @category constructors
|
|
2259
|
+
* @since 2.0.0
|
|
2260
|
+
*/
|
|
2261
|
+
export const gauge: {
|
|
2262
|
+
(name: string, options?: {
|
|
2263
|
+
readonly description?: string | undefined
|
|
2264
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2265
|
+
readonly bigint?: false | undefined
|
|
2266
|
+
}): Gauge<number>
|
|
2267
|
+
(name: string, options: {
|
|
2268
|
+
readonly description?: string | undefined
|
|
2269
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2270
|
+
readonly bigint: true
|
|
2271
|
+
}): Gauge<bigint>
|
|
2272
|
+
} = (name, options) => new GaugeMetric(name, options) as any
|
|
2273
|
+
|
|
2274
|
+
/**
|
|
2275
|
+
* Creates a `Frequency` metric which can be used to count the number of
|
|
2276
|
+
* occurrences of a string.
|
|
2277
|
+
*
|
|
2278
|
+
* **When to use**
|
|
2279
|
+
*
|
|
2280
|
+
* Use when you need a metric for counting how often a specific event or
|
|
2281
|
+
* incident occurs.
|
|
2282
|
+
*
|
|
2283
|
+
* **Details**
|
|
2284
|
+
*
|
|
2285
|
+
* The optional `description` describes the frequency, and `attributes` attach
|
|
2286
|
+
* dimensions to it. Use `preregisteredWords` to initialize occurrence counts
|
|
2287
|
+
* for known string values before updates arrive.
|
|
2288
|
+
*
|
|
2289
|
+
* **Example** (Creating frequency metrics)
|
|
2290
|
+
*
|
|
2291
|
+
* ```ts
|
|
2292
|
+
* import { Data, Effect, Metric } from "effect"
|
|
2293
|
+
*
|
|
2294
|
+
* class FrequencyError extends Data.TaggedError("FrequencyError")<{
|
|
2295
|
+
* readonly operation: string
|
|
2296
|
+
* }> {}
|
|
2297
|
+
*
|
|
2298
|
+
* const program = Effect.gen(function*() {
|
|
2299
|
+
* // Create a frequency metric for HTTP status codes
|
|
2300
|
+
* const statusFrequency = Metric.frequency("http_status_codes", {
|
|
2301
|
+
* description: "Frequency of HTTP response status codes",
|
|
2302
|
+
* preregisteredWords: ["200", "404", "500"] // Pre-register common codes
|
|
2303
|
+
* })
|
|
2304
|
+
*
|
|
2305
|
+
* // Create a frequency metric for user actions
|
|
2306
|
+
* const userActionFrequency = Metric.frequency("user_actions", {
|
|
2307
|
+
* description: "Frequency of user actions performed",
|
|
2308
|
+
* attributes: { application: "web-app" }
|
|
2309
|
+
* })
|
|
2310
|
+
*
|
|
2311
|
+
* // Create a frequency metric for error types
|
|
2312
|
+
* const errorTypeFrequency = Metric.frequency("error_types", {
|
|
2313
|
+
* description: "Frequency of different error types"
|
|
2314
|
+
* })
|
|
2315
|
+
*
|
|
2316
|
+
* // Record different occurrences
|
|
2317
|
+
* yield* Metric.update(statusFrequency, "200") // Success response
|
|
2318
|
+
* yield* Metric.update(statusFrequency, "200") // Another success
|
|
2319
|
+
* yield* Metric.update(statusFrequency, "404") // Not found error
|
|
2320
|
+
* yield* Metric.update(statusFrequency, "500") // Server error
|
|
2321
|
+
* yield* Metric.update(statusFrequency, "200") // Another success
|
|
2322
|
+
*
|
|
2323
|
+
* yield* Metric.update(userActionFrequency, "login")
|
|
2324
|
+
* yield* Metric.update(userActionFrequency, "view_dashboard")
|
|
2325
|
+
* yield* Metric.update(userActionFrequency, "login")
|
|
2326
|
+
* yield* Metric.update(userActionFrequency, "logout")
|
|
2327
|
+
*
|
|
2328
|
+
* yield* Metric.update(errorTypeFrequency, "ValidationError")
|
|
2329
|
+
* yield* Metric.update(errorTypeFrequency, "NetworkError")
|
|
2330
|
+
* yield* Metric.update(errorTypeFrequency, "ValidationError")
|
|
2331
|
+
*
|
|
2332
|
+
* // Get frequency counts
|
|
2333
|
+
* const statusCounts = yield* Metric.value(statusFrequency)
|
|
2334
|
+
* const actionCounts = yield* Metric.value(userActionFrequency)
|
|
2335
|
+
* const errorCounts = yield* Metric.value(errorTypeFrequency)
|
|
2336
|
+
*
|
|
2337
|
+
* // statusCounts.occurrences will be:
|
|
2338
|
+
* // Map { "200" => 3, "404" => 1, "500" => 1 }
|
|
2339
|
+
* // actionCounts.occurrences will be:
|
|
2340
|
+
* // Map { "login" => 2, "view_dashboard" => 1, "logout" => 1 }
|
|
2341
|
+
* // errorCounts.occurrences will be:
|
|
2342
|
+
* // Map { "ValidationError" => 2, "NetworkError" => 1 }
|
|
2343
|
+
*
|
|
2344
|
+
* return { statusCounts, actionCounts, errorCounts }
|
|
2345
|
+
* })
|
|
2346
|
+
* ```
|
|
2347
|
+
*
|
|
2348
|
+
* @category constructors
|
|
2349
|
+
* @since 2.0.0
|
|
2350
|
+
*/
|
|
2351
|
+
export const frequency = (name: string, options?: {
|
|
2352
|
+
readonly description?: string | undefined
|
|
2353
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2354
|
+
readonly preregisteredWords?: ReadonlyArray<string> | undefined
|
|
2355
|
+
}): Frequency => new FrequencyMetric(name, options)
|
|
2356
|
+
|
|
2357
|
+
/**
|
|
2358
|
+
* Represents a `Histogram` metric that records observations into buckets.
|
|
2359
|
+
*
|
|
2360
|
+
* **When to use**
|
|
2361
|
+
*
|
|
2362
|
+
* Use when you need a metric for measuring the distribution of values within a
|
|
2363
|
+
* range.
|
|
2364
|
+
*
|
|
2365
|
+
* **Details**
|
|
2366
|
+
*
|
|
2367
|
+
* The optional `description` describes the histogram, and `attributes` attach
|
|
2368
|
+
* dimensions to it. The required `boundaries` option defines the histogram
|
|
2369
|
+
* bucket boundaries.
|
|
2370
|
+
*
|
|
2371
|
+
* **Example** (Creating histogram metrics)
|
|
2372
|
+
*
|
|
2373
|
+
* ```ts
|
|
2374
|
+
* import { Data, Effect, Metric } from "effect"
|
|
2375
|
+
*
|
|
2376
|
+
* class HistogramError extends Data.TaggedError("HistogramError")<{
|
|
2377
|
+
* readonly operation: string
|
|
2378
|
+
* }> {}
|
|
2379
|
+
*
|
|
2380
|
+
* const program = Effect.gen(function*() {
|
|
2381
|
+
* // Create a histogram for API response times
|
|
2382
|
+
* const responseTimeHistogram = Metric.histogram("api_response_time", {
|
|
2383
|
+
* description: "Distribution of API response times in milliseconds",
|
|
2384
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 50, count: 10 })
|
|
2385
|
+
* // Creates buckets: 0-50ms, 50-100ms, 100-150ms, ..., 400-450ms, 450ms+
|
|
2386
|
+
* })
|
|
2387
|
+
*
|
|
2388
|
+
* // Create a histogram for request payload sizes
|
|
2389
|
+
* const payloadSizeHistogram = Metric.histogram("payload_size", {
|
|
2390
|
+
* description: "Distribution of request payload sizes in KB",
|
|
2391
|
+
* boundaries: Metric.exponentialBoundaries({ start: 1, factor: 2, count: 8 }),
|
|
2392
|
+
* // Creates exponential buckets: 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, 64KB, 128KB+
|
|
2393
|
+
* attributes: { service: "api-gateway" }
|
|
2394
|
+
* })
|
|
2395
|
+
*
|
|
2396
|
+
* // Create a histogram with custom boundaries
|
|
2397
|
+
* const customHistogram = Metric.histogram("custom_metric", {
|
|
2398
|
+
* description: "Custom distribution metric",
|
|
2399
|
+
* boundaries: [0.1, 0.5, 1, 2.5, 5, 10, 25, 50, 100]
|
|
2400
|
+
* })
|
|
2401
|
+
*
|
|
2402
|
+
* // Record various response times
|
|
2403
|
+
* yield* Metric.update(responseTimeHistogram, 25) // Goes in 0-50ms bucket
|
|
2404
|
+
* yield* Metric.update(responseTimeHistogram, 75) // Goes in 50-100ms bucket
|
|
2405
|
+
* yield* Metric.update(responseTimeHistogram, 125) // Goes in 100-150ms bucket
|
|
2406
|
+
* yield* Metric.update(responseTimeHistogram, 200) // Goes in 150-200ms bucket
|
|
2407
|
+
* yield* Metric.update(responseTimeHistogram, 75) // Another 50-100ms
|
|
2408
|
+
*
|
|
2409
|
+
* // Record payload sizes
|
|
2410
|
+
* yield* Metric.update(payloadSizeHistogram, 3) // Goes in 2-4KB bucket
|
|
2411
|
+
* yield* Metric.update(payloadSizeHistogram, 15) // Goes in 8-16KB bucket
|
|
2412
|
+
* yield* Metric.update(payloadSizeHistogram, 0.5) // Goes in 0-1KB bucket
|
|
2413
|
+
*
|
|
2414
|
+
* // Get histogram state with distribution data
|
|
2415
|
+
* const responseTimeState = yield* Metric.value(responseTimeHistogram)
|
|
2416
|
+
* const payloadSizeState = yield* Metric.value(payloadSizeHistogram)
|
|
2417
|
+
*
|
|
2418
|
+
* // responseTimeState will contain:
|
|
2419
|
+
* // - buckets: [[50, 1], [100, 3], [150, 4], [200, 5], ...]
|
|
2420
|
+
* // - count: 5, min: 25, max: 200, sum: 500
|
|
2421
|
+
* // - Useful for calculating percentiles, averages, etc.
|
|
2422
|
+
*
|
|
2423
|
+
* return { responseTimeState, payloadSizeState }
|
|
2424
|
+
* })
|
|
2425
|
+
* ```
|
|
2426
|
+
*
|
|
2427
|
+
* @category constructors
|
|
2428
|
+
* @since 2.0.0
|
|
2429
|
+
*/
|
|
2430
|
+
export const histogram = (name: string, options: {
|
|
2431
|
+
readonly description?: string | undefined
|
|
2432
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2433
|
+
readonly boundaries: ReadonlyArray<number>
|
|
2434
|
+
}): Histogram<number> => new HistogramMetric(name, options)
|
|
2435
|
+
|
|
2436
|
+
/**
|
|
2437
|
+
* Creates a `Summary` metric that records observations and calculates quantiles
|
|
2438
|
+
* which takes a value as input and uses the current time.
|
|
2439
|
+
*
|
|
2440
|
+
* **When to use**
|
|
2441
|
+
*
|
|
2442
|
+
* Use when you need a metric that records statistical information about a set
|
|
2443
|
+
* of values, including quantiles.
|
|
2444
|
+
*
|
|
2445
|
+
* **Details**
|
|
2446
|
+
*
|
|
2447
|
+
* The optional `description` describes the summary, and `attributes` attach
|
|
2448
|
+
* dimensions to it. `maxAge` controls how long observations are retained,
|
|
2449
|
+
* `maxSize` controls how many observations are kept, and `quantiles` lists the
|
|
2450
|
+
* quantiles to calculate, such as `[0.5, 0.9]`.
|
|
2451
|
+
*
|
|
2452
|
+
* **Example** (Creating summary metrics)
|
|
2453
|
+
*
|
|
2454
|
+
* ```ts
|
|
2455
|
+
* import { Data, Duration, Effect, Metric } from "effect"
|
|
2456
|
+
*
|
|
2457
|
+
* class SummaryError extends Data.TaggedError("SummaryError")<{
|
|
2458
|
+
* readonly operation: string
|
|
2459
|
+
* }> {}
|
|
2460
|
+
*
|
|
2461
|
+
* const program = Effect.gen(function*() {
|
|
2462
|
+
* // Create a summary for API response times
|
|
2463
|
+
* const responseTimeSummary = Metric.summary("api_response_time", {
|
|
2464
|
+
* description: "API response time quantiles over 5-minute windows",
|
|
2465
|
+
* maxAge: Duration.minutes(5), // Keep observations for 5 minutes
|
|
2466
|
+
* maxSize: 1000, // Maximum 1000 observations in memory
|
|
2467
|
+
* quantiles: [0.5, 0.9, 0.95, 0.99] // 50th, 90th, 95th, 99th percentiles
|
|
2468
|
+
* })
|
|
2469
|
+
*
|
|
2470
|
+
* // Create a summary for request payload sizes
|
|
2471
|
+
* const payloadSizeSummary = Metric.summary("request_payload_size", {
|
|
2472
|
+
* description: "Request payload size distribution over 2-minute windows",
|
|
2473
|
+
* maxAge: Duration.minutes(2), // Shorter window for recent trends
|
|
2474
|
+
* maxSize: 500, // Smaller buffer for memory efficiency
|
|
2475
|
+
* quantiles: [0.5, 0.75, 0.9], // Median, 75th, 90th percentiles
|
|
2476
|
+
* attributes: { service: "upload-service" }
|
|
2477
|
+
* })
|
|
2478
|
+
*
|
|
2479
|
+
* // Record deterministic response times
|
|
2480
|
+
* const responseTimes = [82, 96, 104, 118, 135, 170, 210, 240]
|
|
2481
|
+
* for (const responseTime of responseTimes) {
|
|
2482
|
+
* yield* Metric.update(responseTimeSummary, responseTime)
|
|
2483
|
+
* }
|
|
2484
|
+
*
|
|
2485
|
+
* // Record some payload sizes
|
|
2486
|
+
* yield* Metric.update(payloadSizeSummary, 1.2) // 1.2KB
|
|
2487
|
+
* yield* Metric.update(payloadSizeSummary, 5.8) // 5.8KB
|
|
2488
|
+
* yield* Metric.update(payloadSizeSummary, 15.6) // 15.6KB
|
|
2489
|
+
* yield* Metric.update(payloadSizeSummary, 3.4) // 3.4KB
|
|
2490
|
+
*
|
|
2491
|
+
* // Get summary statistics with quantiles
|
|
2492
|
+
* const responseStats = yield* Metric.value(responseTimeSummary)
|
|
2493
|
+
* const payloadStats = yield* Metric.value(payloadSizeSummary)
|
|
2494
|
+
*
|
|
2495
|
+
* console.log({
|
|
2496
|
+
* count: responseStats.count,
|
|
2497
|
+
* min: responseStats.min,
|
|
2498
|
+
* max: responseStats.max,
|
|
2499
|
+
* sum: responseStats.sum
|
|
2500
|
+
* }) // { count: 8, min: 82, max: 240, sum: 1155 }
|
|
2501
|
+
*
|
|
2502
|
+
* console.log({
|
|
2503
|
+
* count: payloadStats.count,
|
|
2504
|
+
* min: payloadStats.min,
|
|
2505
|
+
* max: payloadStats.max,
|
|
2506
|
+
* sum: payloadStats.sum
|
|
2507
|
+
* }) // { count: 4, min: 1.2, max: 15.6, sum: 26 }
|
|
2508
|
+
*
|
|
2509
|
+
* // Both summaries include quantile information for their configured windows.
|
|
2510
|
+
*
|
|
2511
|
+
* return { responseStats, payloadStats }
|
|
2512
|
+
* })
|
|
2513
|
+
* ```
|
|
2514
|
+
*
|
|
2515
|
+
* @category constructors
|
|
2516
|
+
* @since 2.0.0
|
|
2517
|
+
*/
|
|
2518
|
+
export const summary = (name: string, options: {
|
|
2519
|
+
readonly description?: string | undefined
|
|
2520
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2521
|
+
readonly maxAge: Duration.Input
|
|
2522
|
+
readonly maxSize: number
|
|
2523
|
+
readonly quantiles: ReadonlyArray<number>
|
|
2524
|
+
}): Summary<number> =>
|
|
2525
|
+
mapInput(summaryWithTimestamp(name, options), (input, context) =>
|
|
2526
|
+
[
|
|
2527
|
+
input,
|
|
2528
|
+
Context.get(context, InternalEffect.ClockRef).currentTimeMillisUnsafe()
|
|
2529
|
+
] as [number, number])
|
|
2530
|
+
|
|
2531
|
+
/**
|
|
2532
|
+
* Creates a `Summary` metric that records observations with explicit
|
|
2533
|
+
* timestamps and calculates quantiles.
|
|
2534
|
+
*
|
|
2535
|
+
* **When to use**
|
|
2536
|
+
*
|
|
2537
|
+
* Use when you need a metric that records statistical information about a set
|
|
2538
|
+
* of values together with timestamps.
|
|
2539
|
+
*
|
|
2540
|
+
* **Details**
|
|
2541
|
+
*
|
|
2542
|
+
* Inputs to this metric are `[value, timestamp]` pairs; the current clock is
|
|
2543
|
+
* used when reading quantiles against the configured `maxAge`.
|
|
2544
|
+
*
|
|
2545
|
+
* The optional `description` describes the summary, and `attributes` attach
|
|
2546
|
+
* dimensions to it. `maxAge` controls how long observations are retained,
|
|
2547
|
+
* `maxSize` controls how many observations are kept, and `quantiles` lists the
|
|
2548
|
+
* quantiles to calculate, such as `[0.5, 0.9]`.
|
|
2549
|
+
*
|
|
2550
|
+
* **Example** (Creating summaries with explicit timestamps)
|
|
2551
|
+
*
|
|
2552
|
+
* ```ts
|
|
2553
|
+
* import { Metric } from "effect"
|
|
2554
|
+
*
|
|
2555
|
+
* const responseTimesSummary = Metric.summaryWithTimestamp(
|
|
2556
|
+
* "response_times_summary",
|
|
2557
|
+
* {
|
|
2558
|
+
* description: "Measures the distribution of response times",
|
|
2559
|
+
* maxAge: "60 seconds", // Retain observations for 60 seconds.
|
|
2560
|
+
* maxSize: 1000, // Keep a maximum of 1000 observations.
|
|
2561
|
+
* quantiles: [0.5, 0.9, 0.99] // Calculate 50th, 90th, and 99th quantiles.
|
|
2562
|
+
* }
|
|
2563
|
+
* )
|
|
2564
|
+
* ```
|
|
2565
|
+
*
|
|
2566
|
+
* @category constructors
|
|
2567
|
+
* @since 4.0.0
|
|
2568
|
+
*/
|
|
2569
|
+
export const summaryWithTimestamp = (name: string, options: {
|
|
2570
|
+
readonly description?: string | undefined
|
|
2571
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2572
|
+
readonly maxAge: Duration.Input
|
|
2573
|
+
readonly maxSize: number
|
|
2574
|
+
readonly quantiles: ReadonlyArray<number>
|
|
2575
|
+
}): Summary<[value: number, timestamp: number]> => new SummaryMetric(name, options)
|
|
2576
|
+
|
|
2577
|
+
/**
|
|
2578
|
+
* Creates a timer metric, based on a `Histogram`, which keeps track of
|
|
2579
|
+
* durations in milliseconds.
|
|
2580
|
+
*
|
|
2581
|
+
* **Details**
|
|
2582
|
+
*
|
|
2583
|
+
* The unit of time will automatically be added to the metric as a tag (i.e.
|
|
2584
|
+
* `"time_unit: milliseconds"`).
|
|
2585
|
+
*
|
|
2586
|
+
* If `options.boundaries` is not provided, the boundaries will be computed
|
|
2587
|
+
* using `Metric.exponentialBoundaries({ start: 0.5, factor: 2, count: 35 })`.
|
|
2588
|
+
*
|
|
2589
|
+
* **Example** (Recording durations with a timer)
|
|
2590
|
+
*
|
|
2591
|
+
* ```ts
|
|
2592
|
+
* import { Data, Duration, Effect, Metric } from "effect"
|
|
2593
|
+
*
|
|
2594
|
+
* class TimerError extends Data.TaggedError("TimerError")<{
|
|
2595
|
+
* readonly operation: string
|
|
2596
|
+
* }> {}
|
|
2597
|
+
*
|
|
2598
|
+
* // Create a timer metric to track API request durations
|
|
2599
|
+
* const apiRequestTimer = Metric.timer("api_request_duration", {
|
|
2600
|
+
* description: "Duration of API requests",
|
|
2601
|
+
* attributes: { service: "user-api" }
|
|
2602
|
+
* })
|
|
2603
|
+
*
|
|
2604
|
+
* // Record a measured API operation duration
|
|
2605
|
+
* const apiOperation = Effect.gen(function*() {
|
|
2606
|
+
* const duration = Duration.millis(120)
|
|
2607
|
+
* yield* Metric.update(apiRequestTimer, duration)
|
|
2608
|
+
*
|
|
2609
|
+
* const state = yield* Metric.value(apiRequestTimer)
|
|
2610
|
+
* console.log({
|
|
2611
|
+
* count: state.count,
|
|
2612
|
+
* min: state.min,
|
|
2613
|
+
* max: state.max,
|
|
2614
|
+
* sum: state.sum
|
|
2615
|
+
* }) // { count: 1, min: 120, max: 120, sum: 120 }
|
|
2616
|
+
* })
|
|
2617
|
+
* ```
|
|
2618
|
+
*
|
|
2619
|
+
* @category constructors
|
|
2620
|
+
* @since 2.0.0
|
|
2621
|
+
*/
|
|
2622
|
+
export const timer = (name: string, options?: {
|
|
2623
|
+
readonly description?: string | undefined
|
|
2624
|
+
readonly attributes?: Metric.Attributes | undefined
|
|
2625
|
+
readonly boundaries?: ReadonlyArray<number>
|
|
2626
|
+
}): Histogram<Duration.Duration> => {
|
|
2627
|
+
const boundaries = Predicate.isNotUndefined(options?.boundaries)
|
|
2628
|
+
? options.boundaries
|
|
2629
|
+
: exponentialBoundaries({ start: 0.5, factor: 2, count: 35 })
|
|
2630
|
+
const attributes = mergeAttributes(options?.attributes, { time_unit: "milliseconds" })
|
|
2631
|
+
const metric = new HistogramMetric(name, { ...options, boundaries, attributes })
|
|
2632
|
+
return mapInput(metric, Duration.toMillis)
|
|
2633
|
+
}
|
|
2634
|
+
|
|
2635
|
+
/**
|
|
2636
|
+
* Retrieves the current state of the specified `Metric`.
|
|
2637
|
+
*
|
|
2638
|
+
* **Details**
|
|
2639
|
+
*
|
|
2640
|
+
* The returned state depends on the metric type. Counters return
|
|
2641
|
+
* `CounterState<number | bigint>` with `count` and `incremental`, gauges return
|
|
2642
|
+
* `GaugeState<number | bigint>` with `value`, frequencies return
|
|
2643
|
+
* `FrequencyState` with `occurrences`, histograms return `HistogramState` with
|
|
2644
|
+
* buckets, count, min, max, and sum, and summaries return `SummaryState` with
|
|
2645
|
+
* quantiles, count, min, max, and sum.
|
|
2646
|
+
*
|
|
2647
|
+
* **Example** (Reading metric state)
|
|
2648
|
+
*
|
|
2649
|
+
* ```ts
|
|
2650
|
+
* import { Effect, Metric } from "effect"
|
|
2651
|
+
*
|
|
2652
|
+
* const requestCounter = Metric.counter("requests")
|
|
2653
|
+
* const responseTime = Metric.histogram("response_time", {
|
|
2654
|
+
* boundaries: [100, 500, 1000, 2000]
|
|
2655
|
+
* })
|
|
2656
|
+
*
|
|
2657
|
+
* const program = Effect.gen(function*() {
|
|
2658
|
+
* // Update metrics
|
|
2659
|
+
* yield* Metric.update(requestCounter, 1)
|
|
2660
|
+
* yield* Metric.update(responseTime, 750)
|
|
2661
|
+
*
|
|
2662
|
+
* // Get current values
|
|
2663
|
+
* const counterState = yield* Metric.value(requestCounter)
|
|
2664
|
+
* console.log(`Request count: ${counterState.count}`)
|
|
2665
|
+
*
|
|
2666
|
+
* const histogramState = yield* Metric.value(responseTime)
|
|
2667
|
+
* console.log(`Response time stats:`, {
|
|
2668
|
+
* count: histogramState.count,
|
|
2669
|
+
* min: histogramState.min,
|
|
2670
|
+
* max: histogramState.max,
|
|
2671
|
+
* average: histogramState.sum / histogramState.count
|
|
2672
|
+
* })
|
|
2673
|
+
* })
|
|
2674
|
+
* ```
|
|
2675
|
+
*
|
|
2676
|
+
* @category getters
|
|
2677
|
+
* @since 2.0.0
|
|
2678
|
+
*/
|
|
2679
|
+
export const value = <Input, State>(
|
|
2680
|
+
self: Metric<Input, State>
|
|
2681
|
+
): Effect<State> =>
|
|
2682
|
+
InternalEffect.flatMap(
|
|
2683
|
+
InternalEffect.context(),
|
|
2684
|
+
(context) => InternalEffect.sync(() => self.valueUnsafe(context))
|
|
2685
|
+
)
|
|
2686
|
+
|
|
2687
|
+
/**
|
|
2688
|
+
* Modifies the metric with the specified input.
|
|
2689
|
+
*
|
|
2690
|
+
* **Details**
|
|
2691
|
+
*
|
|
2692
|
+
* The behavior of `modify` depends on the metric type. Counters add the input
|
|
2693
|
+
* value to the current count, gauges add the input value to the current gauge
|
|
2694
|
+
* value, frequencies increment the occurrence count for the input string,
|
|
2695
|
+
* histograms record the input value in the appropriate bucket, and summaries
|
|
2696
|
+
* record the input observation.
|
|
2697
|
+
*
|
|
2698
|
+
* **Example** (Modifying metric values)
|
|
2699
|
+
*
|
|
2700
|
+
* ```ts
|
|
2701
|
+
* import { Effect, Metric } from "effect"
|
|
2702
|
+
*
|
|
2703
|
+
* const temperatureGauge = Metric.gauge("temperature")
|
|
2704
|
+
* const requestCounter = Metric.counter("requests")
|
|
2705
|
+
*
|
|
2706
|
+
* const program = Effect.gen(function*() {
|
|
2707
|
+
* // Set initial temperature
|
|
2708
|
+
* yield* Metric.update(temperatureGauge, 20)
|
|
2709
|
+
*
|
|
2710
|
+
* // Modify by adding/subtracting values
|
|
2711
|
+
* yield* Metric.modify(temperatureGauge, 5) // Now 25
|
|
2712
|
+
* yield* Metric.modify(temperatureGauge, -3) // Now 22
|
|
2713
|
+
*
|
|
2714
|
+
* // For counters, modify increments by the specified amount
|
|
2715
|
+
* yield* Metric.modify(requestCounter, 10) // Add 10 to counter
|
|
2716
|
+
* yield* Metric.modify(requestCounter, 5) // Add 5 more (total: 15)
|
|
2717
|
+
*
|
|
2718
|
+
* const temp = yield* Metric.value(temperatureGauge)
|
|
2719
|
+
* const requests = yield* Metric.value(requestCounter)
|
|
2720
|
+
*
|
|
2721
|
+
* console.log(`Temperature: ${temp.value}°C`) // 22°C
|
|
2722
|
+
* console.log(`Requests: ${requests.count}`) // 15
|
|
2723
|
+
* })
|
|
2724
|
+
* ```
|
|
2725
|
+
*
|
|
2726
|
+
* @category mutations
|
|
2727
|
+
* @since 3.6.5
|
|
2728
|
+
*/
|
|
2729
|
+
export const modify: {
|
|
2730
|
+
<Input>(input: Input): <State>(self: Metric<Input, State>) => Effect<void>
|
|
2731
|
+
<Input, State>(self: Metric<Input, State>, input: Input): Effect<void>
|
|
2732
|
+
} = dual<
|
|
2733
|
+
<Input>(input: Input) => <State>(self: Metric<Input, State>) => Effect<void>,
|
|
2734
|
+
<Input, State>(self: Metric<Input, State>, input: Input) => Effect<void>
|
|
2735
|
+
>(2, (self, input) =>
|
|
2736
|
+
InternalEffect.flatMap(
|
|
2737
|
+
InternalEffect.context(),
|
|
2738
|
+
(context) => InternalEffect.sync(() => self.modifyUnsafe(input, context))
|
|
2739
|
+
))
|
|
2740
|
+
|
|
2741
|
+
/**
|
|
2742
|
+
* Updates the metric with the specified input.
|
|
2743
|
+
*
|
|
2744
|
+
* **Details**
|
|
2745
|
+
*
|
|
2746
|
+
* The behavior of `update` depends on the metric type. Counters add the input
|
|
2747
|
+
* value to the current count, gauges replace the current value with the input
|
|
2748
|
+
* value, frequencies increment the occurrence count for the input string,
|
|
2749
|
+
* histograms record the input value in the appropriate bucket, and summaries
|
|
2750
|
+
* record the input value as a new observation.
|
|
2751
|
+
*
|
|
2752
|
+
* **Example** (Updating metric values)
|
|
2753
|
+
*
|
|
2754
|
+
* ```ts
|
|
2755
|
+
* import { Effect, Metric } from "effect"
|
|
2756
|
+
*
|
|
2757
|
+
* const cpuUsage = Metric.gauge("cpu_usage_percent")
|
|
2758
|
+
* const httpStatus = Metric.frequency("http_status_codes")
|
|
2759
|
+
* const responseTime = Metric.histogram("response_time_ms", {
|
|
2760
|
+
* boundaries: [100, 500, 1000, 2000]
|
|
2761
|
+
* })
|
|
2762
|
+
*
|
|
2763
|
+
* const program = Effect.gen(function*() {
|
|
2764
|
+
* // Update gauge to specific values
|
|
2765
|
+
* yield* Metric.update(cpuUsage, 45.2)
|
|
2766
|
+
* yield* Metric.update(cpuUsage, 67.8) // Replaces previous value
|
|
2767
|
+
*
|
|
2768
|
+
* // Track HTTP status code occurrences
|
|
2769
|
+
* yield* Metric.update(httpStatus, "200")
|
|
2770
|
+
* yield* Metric.update(httpStatus, "404")
|
|
2771
|
+
* yield* Metric.update(httpStatus, "200") // Increments 200 count
|
|
2772
|
+
*
|
|
2773
|
+
* // Record response times
|
|
2774
|
+
* yield* Metric.update(responseTime, 250)
|
|
2775
|
+
* yield* Metric.update(responseTime, 750)
|
|
2776
|
+
* yield* Metric.update(responseTime, 1500)
|
|
2777
|
+
*
|
|
2778
|
+
* // Check current states
|
|
2779
|
+
* const cpu = yield* Metric.value(cpuUsage)
|
|
2780
|
+
* const statuses = yield* Metric.value(httpStatus)
|
|
2781
|
+
* const times = yield* Metric.value(responseTime)
|
|
2782
|
+
*
|
|
2783
|
+
* console.log(`CPU Usage: ${cpu.value}%`)
|
|
2784
|
+
* console.log(`Status 200 count: ${statuses.occurrences.get("200")}`) // 2
|
|
2785
|
+
* console.log(`Response time samples: ${times.count}`) // 3
|
|
2786
|
+
* })
|
|
2787
|
+
* ```
|
|
2788
|
+
*
|
|
2789
|
+
* @category mutations
|
|
2790
|
+
* @since 2.0.0
|
|
2791
|
+
*/
|
|
2792
|
+
export const update: {
|
|
2793
|
+
<Input>(input: Input): <State>(self: Metric<Input, State>) => Effect<void>
|
|
2794
|
+
<Input, State>(self: Metric<Input, State>, input: Input): Effect<void>
|
|
2795
|
+
} = dual<
|
|
2796
|
+
<Input>(input: Input) => <State>(self: Metric<Input, State>) => Effect<void>,
|
|
2797
|
+
<Input, State>(self: Metric<Input, State>, input: Input) => Effect<void>
|
|
2798
|
+
>(
|
|
2799
|
+
2,
|
|
2800
|
+
(self, input) =>
|
|
2801
|
+
InternalEffect.contextWith((services) => InternalEffect.sync(() => self.updateUnsafe(input, services)))
|
|
2802
|
+
)
|
|
2803
|
+
|
|
2804
|
+
/**
|
|
2805
|
+
* Returns a new metric that is powered by this one, but which accepts updates
|
|
2806
|
+
* of the specified new type, which must be transformable to the input type of
|
|
2807
|
+
* this metric.
|
|
2808
|
+
*
|
|
2809
|
+
* **Example** (Mapping metric inputs)
|
|
2810
|
+
*
|
|
2811
|
+
* ```ts
|
|
2812
|
+
* import { Data, Effect, Metric } from "effect"
|
|
2813
|
+
*
|
|
2814
|
+
* class MetricError extends Data.TaggedError("MetricError")<{
|
|
2815
|
+
* readonly operation: string
|
|
2816
|
+
* }> {}
|
|
2817
|
+
*
|
|
2818
|
+
* // Create a histogram that expects Duration values
|
|
2819
|
+
* const durationHistogram = Metric.histogram("request_duration_ms", {
|
|
2820
|
+
* description: "Request duration in milliseconds",
|
|
2821
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 100, count: 10 })
|
|
2822
|
+
* })
|
|
2823
|
+
*
|
|
2824
|
+
* // Transform to accept number values representing milliseconds
|
|
2825
|
+
* const numberHistogram = Metric.mapInput(
|
|
2826
|
+
* durationHistogram,
|
|
2827
|
+
* (ms: number) => ms // Direct mapping from number to expected input
|
|
2828
|
+
* )
|
|
2829
|
+
*
|
|
2830
|
+
* const program = Effect.gen(function*() {
|
|
2831
|
+
* // Now we can update with a plain number
|
|
2832
|
+
* yield* Metric.update(numberHistogram, 250)
|
|
2833
|
+
*
|
|
2834
|
+
* // Get metric value to see the recorded state
|
|
2835
|
+
* const value = yield* Metric.value(numberHistogram)
|
|
2836
|
+
* return value
|
|
2837
|
+
* })
|
|
2838
|
+
* ```
|
|
2839
|
+
*
|
|
2840
|
+
* @category mapping
|
|
2841
|
+
* @since 2.0.0
|
|
2842
|
+
*/
|
|
2843
|
+
export const mapInput: {
|
|
2844
|
+
<Input, Input2 extends Input>(
|
|
2845
|
+
f: (input: Input2, context: Context.Context<never>) => Input
|
|
2846
|
+
): <State>(self: Metric<Input, State>) => Metric<Input2, State>
|
|
2847
|
+
<Input, State, Input2>(
|
|
2848
|
+
self: Metric<Input, State>,
|
|
2849
|
+
f: (input: Input2, context: Context.Context<never>) => Input
|
|
2850
|
+
): Metric<Input2, State>
|
|
2851
|
+
} = dual<
|
|
2852
|
+
<Input, Input2 extends Input>(
|
|
2853
|
+
f: (input: Input2, context: Context.Context<never>) => Input
|
|
2854
|
+
) => <State>(self: Metric<Input, State>) => Metric<Input2, State>,
|
|
2855
|
+
<Input, State, Input2>(
|
|
2856
|
+
self: Metric<Input, State>,
|
|
2857
|
+
f: (input: Input2, context: Context.Context<never>) => Input
|
|
2858
|
+
) => Metric<Input2, State>
|
|
2859
|
+
>(2, <Input, State, Input2>(
|
|
2860
|
+
self: Metric<Input, State>,
|
|
2861
|
+
f: (input: Input2, context: Context.Context<never>) => Input
|
|
2862
|
+
): Metric<Input2, State> =>
|
|
2863
|
+
new MetricTransform(
|
|
2864
|
+
self,
|
|
2865
|
+
(context) => self.valueUnsafe(context),
|
|
2866
|
+
(input, context) => self.updateUnsafe(f(input, context), context),
|
|
2867
|
+
(input, context) => self.modifyUnsafe(f(input, context), context)
|
|
2868
|
+
))
|
|
2869
|
+
|
|
2870
|
+
/**
|
|
2871
|
+
* Returns a new metric that is powered by this one, but which accepts updates
|
|
2872
|
+
* of any type, and translates them to updates with the specified constant
|
|
2873
|
+
* update value.
|
|
2874
|
+
*
|
|
2875
|
+
* **Example** (Ignoring inputs with a constant value)
|
|
2876
|
+
*
|
|
2877
|
+
* ```ts
|
|
2878
|
+
* import { Data, Effect, Metric } from "effect"
|
|
2879
|
+
*
|
|
2880
|
+
* class MetricError extends Data.TaggedError("MetricError")<{
|
|
2881
|
+
* readonly operation: string
|
|
2882
|
+
* }> {}
|
|
2883
|
+
*
|
|
2884
|
+
* // Create a counter that normally expects a number increment
|
|
2885
|
+
* const requestCounter = Metric.counter("total_requests", {
|
|
2886
|
+
* description: "Total number of requests processed"
|
|
2887
|
+
* })
|
|
2888
|
+
*
|
|
2889
|
+
* // Create a version that always increments by 1, regardless of input
|
|
2890
|
+
* const simpleRequestCounter = Metric.withConstantInput(requestCounter, 1)
|
|
2891
|
+
*
|
|
2892
|
+
* const program = Effect.gen(function*() {
|
|
2893
|
+
* // These all increment the counter by 1, ignoring the input value
|
|
2894
|
+
* yield* Metric.update(simpleRequestCounter, "any string")
|
|
2895
|
+
* yield* Metric.update(simpleRequestCounter, { complex: "object" })
|
|
2896
|
+
* yield* Metric.update(simpleRequestCounter, 999) // Still increments by 1
|
|
2897
|
+
*
|
|
2898
|
+
* const value = yield* Metric.value(simpleRequestCounter)
|
|
2899
|
+
* return value // Counter state will show count: 3
|
|
2900
|
+
* })
|
|
2901
|
+
* ```
|
|
2902
|
+
*
|
|
2903
|
+
* @category Input
|
|
2904
|
+
* @since 2.0.0
|
|
2905
|
+
*/
|
|
2906
|
+
export const withConstantInput: {
|
|
2907
|
+
<Input>(input: Input): <State>(self: Metric<Input, State>) => Metric<unknown, State>
|
|
2908
|
+
<Input, State>(self: Metric<Input, State>, input: Input): Metric<unknown, State>
|
|
2909
|
+
} = dual<
|
|
2910
|
+
<Input>(input: Input) => <State>(self: Metric<Input, State>) => Metric<unknown, State>,
|
|
2911
|
+
<Input, State>(self: Metric<Input, State>, input: Input) => Metric<unknown, State>
|
|
2912
|
+
>(2, (self, input) => mapInput(self, () => input))
|
|
2913
|
+
|
|
2914
|
+
/**
|
|
2915
|
+
* Returns a new metric that applies the specified attributes to all operations.
|
|
2916
|
+
*
|
|
2917
|
+
* **Details**
|
|
2918
|
+
*
|
|
2919
|
+
* Attributes are key-value pairs that provide additional context for metrics,
|
|
2920
|
+
* enabling filtering, grouping, and more detailed analysis. Each combination
|
|
2921
|
+
* of attribute values creates a separate metric series.
|
|
2922
|
+
*
|
|
2923
|
+
* **Example** (Applying metric attributes)
|
|
2924
|
+
*
|
|
2925
|
+
* ```ts
|
|
2926
|
+
* import { Effect, Metric } from "effect"
|
|
2927
|
+
*
|
|
2928
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
2929
|
+
* description: "Total HTTP requests"
|
|
2930
|
+
* })
|
|
2931
|
+
*
|
|
2932
|
+
* // Create tagged versions of the metric
|
|
2933
|
+
* const getRequests = Metric.withAttributes(requestCounter, {
|
|
2934
|
+
* method: "GET",
|
|
2935
|
+
* endpoint: "/api/users"
|
|
2936
|
+
* })
|
|
2937
|
+
*
|
|
2938
|
+
* const postRequests = Metric.withAttributes(requestCounter, {
|
|
2939
|
+
* method: "POST",
|
|
2940
|
+
* endpoint: "/api/users"
|
|
2941
|
+
* })
|
|
2942
|
+
*
|
|
2943
|
+
* const program = Effect.gen(function*() {
|
|
2944
|
+
* // These will be tracked as separate metric series
|
|
2945
|
+
* yield* Metric.update(getRequests, 1) // http_requests_total{method="GET", endpoint="/api/users"}
|
|
2946
|
+
* yield* Metric.update(postRequests, 1) // http_requests_total{method="POST", endpoint="/api/users"}
|
|
2947
|
+
* yield* Metric.update(getRequests, 1) // Increments the GET counter
|
|
2948
|
+
*
|
|
2949
|
+
* // You can also chain attributes
|
|
2950
|
+
* const taggedMetric = requestCounter.pipe(
|
|
2951
|
+
* Metric.withAttributes({ service: "user-api" }),
|
|
2952
|
+
* Metric.withAttributes({ version: "v1" })
|
|
2953
|
+
* )
|
|
2954
|
+
*
|
|
2955
|
+
* yield* Metric.update(taggedMetric, 1) // http_requests_total{service="user-api", version="v1"}
|
|
2956
|
+
* })
|
|
2957
|
+
*
|
|
2958
|
+
* // When taking snapshots, each attribute combination appears as a separate metric
|
|
2959
|
+
* const viewMetrics = Effect.gen(function*() {
|
|
2960
|
+
* const snapshots = yield* Metric.snapshot
|
|
2961
|
+
* for (const metric of snapshots) {
|
|
2962
|
+
* if (metric.id === "http_requests_total") {
|
|
2963
|
+
* console.log(`${metric.id}`, metric.attributes, metric.state)
|
|
2964
|
+
* }
|
|
2965
|
+
* }
|
|
2966
|
+
* })
|
|
2967
|
+
* ```
|
|
2968
|
+
*
|
|
2969
|
+
* @category Attributes
|
|
2970
|
+
* @since 4.0.0
|
|
2971
|
+
*/
|
|
2972
|
+
export const withAttributes: {
|
|
2973
|
+
(attributes: Metric.Attributes): <Input, State>(self: Metric<Input, State>) => Metric<Input, State>
|
|
2974
|
+
<Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>
|
|
2975
|
+
} = dual<
|
|
2976
|
+
(attributes: Metric.Attributes) => <Input, State>(self: Metric<Input, State>) => Metric<Input, State>,
|
|
2977
|
+
<Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes) => Metric<Input, State>
|
|
2978
|
+
>(2, <Input, State>(
|
|
2979
|
+
self: Metric<Input, State>,
|
|
2980
|
+
attributes: Metric.Attributes
|
|
2981
|
+
): Metric<Input, State> =>
|
|
2982
|
+
new MetricTransform(
|
|
2983
|
+
self,
|
|
2984
|
+
(context) => self.valueUnsafe(addAttributesToContext(context, attributes)),
|
|
2985
|
+
(input, context) => self.updateUnsafe(input, addAttributesToContext(context, attributes)),
|
|
2986
|
+
(input, context) => self.modifyUnsafe(input, addAttributesToContext(context, attributes))
|
|
2987
|
+
))
|
|
2988
|
+
|
|
2989
|
+
// Metric Snapshots
|
|
2990
|
+
|
|
2991
|
+
/**
|
|
2992
|
+
* Captures a snapshot of all registered metrics in the current context.
|
|
2993
|
+
*
|
|
2994
|
+
* **Details**
|
|
2995
|
+
*
|
|
2996
|
+
* Returns an array of metric snapshots, each containing the metric's metadata
|
|
2997
|
+
* (name, description, type) and current state (values, counts, etc.).
|
|
2998
|
+
*
|
|
2999
|
+
* **Example** (Capturing metric snapshots)
|
|
3000
|
+
*
|
|
3001
|
+
* ```ts
|
|
3002
|
+
* import { Console, Data, Effect, Metric } from "effect"
|
|
3003
|
+
*
|
|
3004
|
+
* class SnapshotError extends Data.TaggedError("SnapshotError")<{
|
|
3005
|
+
* readonly operation: string
|
|
3006
|
+
* }> {}
|
|
3007
|
+
*
|
|
3008
|
+
* const program = Effect.gen(function*() {
|
|
3009
|
+
* // Create and update some metrics
|
|
3010
|
+
* const requestCounter = Metric.counter("http_requests", {
|
|
3011
|
+
* description: "Total HTTP requests"
|
|
3012
|
+
* })
|
|
3013
|
+
* const responseTime = Metric.histogram("response_time_ms", {
|
|
3014
|
+
* description: "Response time in milliseconds",
|
|
3015
|
+
* boundaries: Metric.linearBoundaries({ start: 0, width: 100, count: 5 })
|
|
3016
|
+
* })
|
|
3017
|
+
*
|
|
3018
|
+
* // Update the metrics with some values
|
|
3019
|
+
* yield* Metric.update(requestCounter, 1)
|
|
3020
|
+
* yield* Metric.update(requestCounter, 1)
|
|
3021
|
+
* yield* Metric.update(responseTime, 150)
|
|
3022
|
+
* yield* Metric.update(responseTime, 75)
|
|
3023
|
+
*
|
|
3024
|
+
* // Take a snapshot of all metrics
|
|
3025
|
+
* const snapshots = yield* Metric.snapshot
|
|
3026
|
+
*
|
|
3027
|
+
* // Examine the snapshots
|
|
3028
|
+
* for (const snapshot of snapshots) {
|
|
3029
|
+
* yield* Console.log(`Metric: ${snapshot.id}`)
|
|
3030
|
+
* yield* Console.log(`Description: ${snapshot.description}`)
|
|
3031
|
+
* yield* Console.log(`Type: ${snapshot.type}`)
|
|
3032
|
+
* yield* Console.log(`State:`, snapshot.state)
|
|
3033
|
+
* }
|
|
3034
|
+
*
|
|
3035
|
+
* return snapshots
|
|
3036
|
+
* })
|
|
3037
|
+
* ```
|
|
3038
|
+
*
|
|
3039
|
+
* @category Snapshotting
|
|
3040
|
+
* @since 2.0.0
|
|
3041
|
+
*/
|
|
3042
|
+
export const snapshot: Effect<ReadonlyArray<Metric.Snapshot>> = InternalEffect.map(
|
|
3043
|
+
InternalEffect.context(),
|
|
3044
|
+
(context) => snapshotUnsafe(context)
|
|
3045
|
+
)
|
|
3046
|
+
|
|
3047
|
+
/**
|
|
3048
|
+
* Returns a human-readable string representation of all currently registered
|
|
3049
|
+
* metrics in a tabular format.
|
|
3050
|
+
*
|
|
3051
|
+
* **Details**
|
|
3052
|
+
*
|
|
3053
|
+
* This debugging utility captures a snapshot of all metrics and formats them
|
|
3054
|
+
* in an easy-to-read table showing names, descriptions, types, attributes,
|
|
3055
|
+
* and current state values.
|
|
3056
|
+
*
|
|
3057
|
+
* **Example** (Dumping metrics as text)
|
|
3058
|
+
*
|
|
3059
|
+
* ```ts
|
|
3060
|
+
* import { Console, Data, Effect, Metric } from "effect"
|
|
3061
|
+
*
|
|
3062
|
+
* class DumpError extends Data.TaggedError("DumpError")<{
|
|
3063
|
+
* readonly operation: string
|
|
3064
|
+
* }> {}
|
|
3065
|
+
*
|
|
3066
|
+
* const program = Effect.gen(function*() {
|
|
3067
|
+
* // Create and update some metrics for demonstration
|
|
3068
|
+
* const requestCounter = Metric.counter("http_requests_total", {
|
|
3069
|
+
* description: "Total HTTP requests"
|
|
3070
|
+
* })
|
|
3071
|
+
* const responseTime = Metric.gauge("response_time_ms", {
|
|
3072
|
+
* description: "Current response time in milliseconds"
|
|
3073
|
+
* })
|
|
3074
|
+
* const statusFreq = Metric.frequency("http_status_codes", {
|
|
3075
|
+
* description: "Frequency of HTTP status codes"
|
|
3076
|
+
* })
|
|
3077
|
+
*
|
|
3078
|
+
* // Update metrics with some values
|
|
3079
|
+
* yield* Metric.update(requestCounter, 1)
|
|
3080
|
+
* yield* Metric.update(requestCounter, 1)
|
|
3081
|
+
* yield* Metric.update(responseTime, 125)
|
|
3082
|
+
* yield* Metric.update(statusFreq, "200")
|
|
3083
|
+
* yield* Metric.update(statusFreq, "404")
|
|
3084
|
+
* yield* Metric.update(statusFreq, "200")
|
|
3085
|
+
*
|
|
3086
|
+
* // Get formatted dump of all metrics
|
|
3087
|
+
* const metricsReport = yield* Metric.dump
|
|
3088
|
+
* yield* Console.log("Current Metrics:")
|
|
3089
|
+
* yield* Console.log(metricsReport)
|
|
3090
|
+
*
|
|
3091
|
+
* // Output will look like a formatted table:
|
|
3092
|
+
* // Name Description Type State
|
|
3093
|
+
* // http_requests_total Total HTTP requests Counter [count: 2]
|
|
3094
|
+
* // response_time_ms Current response time in milliseconds Gauge [value: 125]
|
|
3095
|
+
* // http_status_codes Frequency of HTTP status codes Frequency [occurrences: 200 -> 2, 404 -> 1]
|
|
3096
|
+
*
|
|
3097
|
+
* return metricsReport
|
|
3098
|
+
* })
|
|
3099
|
+
* ```
|
|
3100
|
+
*
|
|
3101
|
+
* @category Debugging
|
|
3102
|
+
* @since 4.0.0
|
|
3103
|
+
*/
|
|
3104
|
+
export const dump: Effect<string> = InternalEffect.flatMap(InternalEffect.context(), (context) => {
|
|
3105
|
+
const metrics = snapshotUnsafe(context)
|
|
3106
|
+
if (metrics.length > 0) {
|
|
3107
|
+
const maxNameLength = metrics.reduce((max, metric) => {
|
|
3108
|
+
const length = metric.id.length
|
|
3109
|
+
return length > max ? length : max
|
|
3110
|
+
}, 0) + 2
|
|
3111
|
+
const maxDescriptionLength = metrics.reduce((max, metric) => {
|
|
3112
|
+
const length = Predicate.isNotUndefined(metric.description) ? metric.description.length : 0
|
|
3113
|
+
return length > max ? length : max
|
|
3114
|
+
}, 0) + 2
|
|
3115
|
+
const maxTypeLength = metrics.reduce((max, metric) => {
|
|
3116
|
+
const length = metric.type.length
|
|
3117
|
+
return length > max ? length : max
|
|
3118
|
+
}, 0) + 2
|
|
3119
|
+
const maxAttributesLength = metrics.reduce((max, metric) => {
|
|
3120
|
+
const length = Predicate.isNotUndefined(metric.attributes) ? attributesToString(metric.attributes).length : 0
|
|
3121
|
+
return length > max ? length : max
|
|
3122
|
+
}, 0) + 2
|
|
3123
|
+
const grouped = Object.entries(Arr.groupBy(metrics, (metric) => metric.id))
|
|
3124
|
+
const sorted = Arr.sortWith(grouped, (entry) => entry[0], _String.Order)
|
|
3125
|
+
const rendered = sorted.map(([, group]) =>
|
|
3126
|
+
group.map((metric) =>
|
|
3127
|
+
renderName(metric, maxNameLength) +
|
|
3128
|
+
renderDescription(metric, maxDescriptionLength) +
|
|
3129
|
+
renderType(metric, maxTypeLength) +
|
|
3130
|
+
renderAttributes(metric, maxAttributesLength) +
|
|
3131
|
+
renderState(metric)
|
|
3132
|
+
).join("\n")
|
|
3133
|
+
).join("\n")
|
|
3134
|
+
return InternalEffect.succeed(rendered)
|
|
3135
|
+
}
|
|
3136
|
+
return InternalEffect.succeed("")
|
|
3137
|
+
})
|
|
3138
|
+
|
|
3139
|
+
/**
|
|
3140
|
+
* Captures a snapshot of all registered metrics synchronously using the provided
|
|
3141
|
+
* service context.
|
|
3142
|
+
*
|
|
3143
|
+
* **When to use**
|
|
3144
|
+
*
|
|
3145
|
+
* Use to read metric snapshots from an explicit `Context` in low-level
|
|
3146
|
+
* integrations, exporters, or debugging tools that already have the context.
|
|
3147
|
+
*
|
|
3148
|
+
* **Details**
|
|
3149
|
+
*
|
|
3150
|
+
* This is the "unsafe" version that bypasses Effect's safety guarantees and requires
|
|
3151
|
+
* manual handling of the services context. Use the safe `snapshot` function for normal
|
|
3152
|
+
* application code.
|
|
3153
|
+
*
|
|
3154
|
+
* **Example** (Capturing snapshots from a context)
|
|
3155
|
+
*
|
|
3156
|
+
* ```ts
|
|
3157
|
+
* import { Data, Effect, Metric } from "effect"
|
|
3158
|
+
*
|
|
3159
|
+
* class UnsafeSnapshotError extends Data.TaggedError("UnsafeSnapshotError")<{
|
|
3160
|
+
* readonly operation: string
|
|
3161
|
+
* }> {}
|
|
3162
|
+
*
|
|
3163
|
+
* // Use unsafeSnapshot in performance-critical scenarios or internal implementations
|
|
3164
|
+
* const performanceMetricsExporter = Effect.gen(function*() {
|
|
3165
|
+
* // Create some metrics first
|
|
3166
|
+
* const requestCounter = Metric.counter("http_requests", {
|
|
3167
|
+
* description: "Total HTTP requests"
|
|
3168
|
+
* })
|
|
3169
|
+
* const responseTime = Metric.gauge("response_time_ms", {
|
|
3170
|
+
* description: "Current response time"
|
|
3171
|
+
* })
|
|
3172
|
+
*
|
|
3173
|
+
* // Update metrics
|
|
3174
|
+
* yield* Metric.update(requestCounter, 1)
|
|
3175
|
+
* yield* Metric.update(responseTime, 150)
|
|
3176
|
+
*
|
|
3177
|
+
* // Get services context for unsafe operations
|
|
3178
|
+
* const services = yield* Effect.context()
|
|
3179
|
+
*
|
|
3180
|
+
* // Use snapshotUnsafe for direct, synchronous access
|
|
3181
|
+
* const snapshots = Metric.snapshotUnsafe(services)
|
|
3182
|
+
* const exportBatchCreatedAt = 1_700_000_000_000
|
|
3183
|
+
*
|
|
3184
|
+
* // Process snapshots immediately (useful for exporters, debugging tools)
|
|
3185
|
+
* const exportData = snapshots.map((snapshot) => ({
|
|
3186
|
+
* name: snapshot.id,
|
|
3187
|
+
* type: snapshot.type,
|
|
3188
|
+
* value: snapshot.state,
|
|
3189
|
+
* timestamp: exportBatchCreatedAt
|
|
3190
|
+
* }))
|
|
3191
|
+
*
|
|
3192
|
+
* // This is synchronous and doesn't involve Effect overhead
|
|
3193
|
+
* // Useful for performance-critical metric export operations
|
|
3194
|
+
* return exportData
|
|
3195
|
+
* })
|
|
3196
|
+
*
|
|
3197
|
+
* // For normal application use, prefer the safe snapshot function:
|
|
3198
|
+
* const safeSnapshotExample = Effect.gen(function*() {
|
|
3199
|
+
* // This automatically handles the services context
|
|
3200
|
+
* const snapshots = yield* Metric.snapshot
|
|
3201
|
+
* return snapshots
|
|
3202
|
+
* })
|
|
3203
|
+
* ```
|
|
3204
|
+
*
|
|
3205
|
+
* @category Snapshotting
|
|
3206
|
+
* @since 4.0.0
|
|
3207
|
+
*/
|
|
3208
|
+
export const snapshotUnsafe = (context: Context.Context<never>): ReadonlyArray<Metric.Snapshot> => {
|
|
3209
|
+
const registry = Context.get(context, MetricRegistry)
|
|
3210
|
+
return Array.from(registry.values()).map(({ hooks, ...meta }) => ({
|
|
3211
|
+
...meta,
|
|
3212
|
+
state: hooks.get(context)
|
|
3213
|
+
}))
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
const renderName = (metric: Metric.Snapshot, padTo: number): string => `name=${metric.id.padEnd(padTo, " ")}`
|
|
3217
|
+
|
|
3218
|
+
const renderDescription = (metric: Metric.Snapshot, padTo: number): string =>
|
|
3219
|
+
`description=${(metric.description ?? "").padEnd(padTo, " ")}`
|
|
3220
|
+
|
|
3221
|
+
const renderType = (metric: Metric.Snapshot, padTo: number): string => `type=${metric.type.padEnd(padTo, " ")}`
|
|
3222
|
+
|
|
3223
|
+
const renderAttributes = (metric: Metric.Snapshot, padTo: number): string => {
|
|
3224
|
+
const attrs = attributesToString(metric.attributes ?? {})
|
|
3225
|
+
const padding = " ".repeat(Math.max(0, padTo - attrs.length))
|
|
3226
|
+
return `${attrs}${padding}`
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
const renderState = (metric: Metric.Snapshot): string => {
|
|
3230
|
+
const prefix: string = "state="
|
|
3231
|
+
switch (metric.type) {
|
|
3232
|
+
case "Counter": {
|
|
3233
|
+
const state = metric.state as CounterState<number | bigint>
|
|
3234
|
+
return `${prefix}[count: [${state.count}]]`
|
|
3235
|
+
}
|
|
3236
|
+
case "Frequency": {
|
|
3237
|
+
const state = metric.state as FrequencyState
|
|
3238
|
+
return `${prefix}[occurrences: ${renderKeyValues(state.occurrences)}]`
|
|
3239
|
+
}
|
|
3240
|
+
case "Gauge": {
|
|
3241
|
+
const state = metric.state as GaugeState<number | bigint>
|
|
3242
|
+
return `${prefix}[value: [${state.value}]]`
|
|
3243
|
+
}
|
|
3244
|
+
case "Histogram": {
|
|
3245
|
+
const state = metric.state as HistogramState
|
|
3246
|
+
const buckets = `buckets: [${renderKeyValues(state.buckets)}]`
|
|
3247
|
+
const count = `count: [${state.count}]`
|
|
3248
|
+
const min = `min: [${state.min}]`
|
|
3249
|
+
const max = `max: [${state.max}]`
|
|
3250
|
+
const sum = `sum: [${state.sum}]`
|
|
3251
|
+
return `${prefix}[${buckets}, ${count}, ${min}, ${max}, ${sum}]`
|
|
3252
|
+
}
|
|
3253
|
+
case "Summary": {
|
|
3254
|
+
const state = metric.state as SummaryState
|
|
3255
|
+
const printableQuantiles = state.quantiles.map(([key, value]) => [key, value ?? 0] as [number, number])
|
|
3256
|
+
const quantiles = `quantiles: [${renderKeyValues(printableQuantiles)}]`
|
|
3257
|
+
const count = `count: [${state.count}]`
|
|
3258
|
+
const min = `min: [${state.min}]`
|
|
3259
|
+
const max = `max: [${state.max}]`
|
|
3260
|
+
const sum = `sum: [${state.sum}]`
|
|
3261
|
+
return `${prefix}[${quantiles}, ${count}, ${min}, ${max}, ${sum}]`
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
const renderKeyValues = (keyValues: Iterable<[number | string, string | number]>): string =>
|
|
3267
|
+
Array.from(keyValues).map(([key, value]) => `(${key} -> ${value})`).join(", ")
|
|
3268
|
+
|
|
3269
|
+
const attributesToString = (attributes: Metric.AttributeSet): string => {
|
|
3270
|
+
const attrs = Object.entries(attributes)
|
|
3271
|
+
const sorted = Arr.sortWith(attrs, (attr) => attr[0], _String.Order)
|
|
3272
|
+
return `attributes=[${sorted.map(([key, value]) => `${key}: ${value}`).join(", ")}]`
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3275
|
+
// Metric Boundaries
|
|
3276
|
+
|
|
3277
|
+
/**
|
|
3278
|
+
* Creates histogram bucket boundaries from an iterable set of values.
|
|
3279
|
+
*
|
|
3280
|
+
* **Details**
|
|
3281
|
+
*
|
|
3282
|
+
* Processes any iterable of numbers by removing duplicates, filtering out
|
|
3283
|
+
* non-positive values, and automatically appending positive infinity as the
|
|
3284
|
+
* final boundary.
|
|
3285
|
+
*
|
|
3286
|
+
* **Example** (Creating boundaries from values)
|
|
3287
|
+
*
|
|
3288
|
+
* ```ts
|
|
3289
|
+
* import { Data, Effect, Metric } from "effect"
|
|
3290
|
+
*
|
|
3291
|
+
* class BoundaryError extends Data.TaggedError("BoundaryError")<{
|
|
3292
|
+
* readonly operation: string
|
|
3293
|
+
* }> {}
|
|
3294
|
+
*
|
|
3295
|
+
* // Create boundaries from an array of custom values
|
|
3296
|
+
* const customBoundaries = Metric.boundariesFromIterable([
|
|
3297
|
+
* 10,
|
|
3298
|
+
* 25,
|
|
3299
|
+
* 50,
|
|
3300
|
+
* 100,
|
|
3301
|
+
* 250,
|
|
3302
|
+
* 500,
|
|
3303
|
+
* 1000
|
|
3304
|
+
* ])
|
|
3305
|
+
* console.log(customBoundaries) // [10, 25, 50, 100, 250, 500, 1000, Infinity]
|
|
3306
|
+
*
|
|
3307
|
+
* // Automatically removes duplicates and negative values
|
|
3308
|
+
* const messyBoundaries = Metric.boundariesFromIterable([
|
|
3309
|
+
* -5,
|
|
3310
|
+
* 0,
|
|
3311
|
+
* 10,
|
|
3312
|
+
* 10,
|
|
3313
|
+
* 25,
|
|
3314
|
+
* 25,
|
|
3315
|
+
* 50,
|
|
3316
|
+
* -1
|
|
3317
|
+
* ])
|
|
3318
|
+
* console.log(messyBoundaries) // [10, 25, 50, Infinity]
|
|
3319
|
+
*
|
|
3320
|
+
* // Works with any iterable (Set, generator functions, etc.)
|
|
3321
|
+
* const setBoundaries = Metric.boundariesFromIterable(
|
|
3322
|
+
* new Set([100, 200, 300, 200, 100])
|
|
3323
|
+
* )
|
|
3324
|
+
* console.log(setBoundaries) // [100, 200, 300, Infinity]
|
|
3325
|
+
*
|
|
3326
|
+
* // Use with histogram metric
|
|
3327
|
+
* const responseTimeHistogram = Metric.histogram("response_times", {
|
|
3328
|
+
* description: "API response time distribution",
|
|
3329
|
+
* boundaries: customBoundaries
|
|
3330
|
+
* })
|
|
3331
|
+
*
|
|
3332
|
+
* const program = Effect.gen(function*() {
|
|
3333
|
+
* yield* Metric.update(responseTimeHistogram, 75) // Goes in 50-100ms bucket
|
|
3334
|
+
* yield* Metric.update(responseTimeHistogram, 150) // Goes in 100-250ms bucket
|
|
3335
|
+
*
|
|
3336
|
+
* const value = yield* Metric.value(responseTimeHistogram)
|
|
3337
|
+
* return value
|
|
3338
|
+
* })
|
|
3339
|
+
* ```
|
|
3340
|
+
*
|
|
3341
|
+
* @category boundaries
|
|
3342
|
+
* @since 4.0.0
|
|
3343
|
+
*/
|
|
3344
|
+
export const boundariesFromIterable = (iterable: Iterable<number>): ReadonlyArray<number> =>
|
|
3345
|
+
Arr.append(Arr.filter(new Set(iterable), (n) => n > 0), Number.POSITIVE_INFINITY)
|
|
3346
|
+
|
|
3347
|
+
/**
|
|
3348
|
+
* Creates histogram bucket boundaries from a linear sequence and appends
|
|
3349
|
+
* positive infinity.
|
|
3350
|
+
*
|
|
3351
|
+
* **Details**
|
|
3352
|
+
*
|
|
3353
|
+
* Generates `count - 1` finite boundaries using `start + width + index` for
|
|
3354
|
+
* each zero-based index, then applies the same normalization as
|
|
3355
|
+
* `boundariesFromIterable`: non-positive values are removed, duplicates are
|
|
3356
|
+
* collapsed, and `Infinity` is appended.
|
|
3357
|
+
*
|
|
3358
|
+
* **Example** (Creating linear boundaries)
|
|
3359
|
+
*
|
|
3360
|
+
* ```ts
|
|
3361
|
+
* import { Data, Effect, Metric } from "effect"
|
|
3362
|
+
*
|
|
3363
|
+
* class BoundaryError extends Data.TaggedError("BoundaryError")<{
|
|
3364
|
+
* readonly operation: string
|
|
3365
|
+
* }> {}
|
|
3366
|
+
*
|
|
3367
|
+
* // Create boundaries for response time histogram
|
|
3368
|
+
* const responseBoundaries = Metric.linearBoundaries({
|
|
3369
|
+
* start: 0, // Starting point
|
|
3370
|
+
* width: 100, // Offset used for the first boundary
|
|
3371
|
+
* count: 5 // Creates 4 boundaries + infinity
|
|
3372
|
+
* })
|
|
3373
|
+
* console.log(responseBoundaries) // [100, 101, 102, 103, Infinity]
|
|
3374
|
+
*
|
|
3375
|
+
* // Create a histogram using these boundaries
|
|
3376
|
+
* const responseTimeHistogram = Metric.histogram("api_response_time", {
|
|
3377
|
+
* description: "API response time distribution",
|
|
3378
|
+
* boundaries: responseBoundaries
|
|
3379
|
+
* })
|
|
3380
|
+
*
|
|
3381
|
+
* const program = Effect.gen(function*() {
|
|
3382
|
+
* // Record some response times
|
|
3383
|
+
* yield* Metric.update(responseTimeHistogram, 85)
|
|
3384
|
+
* yield* Metric.update(responseTimeHistogram, 101)
|
|
3385
|
+
* yield* Metric.update(responseTimeHistogram, 450)
|
|
3386
|
+
*
|
|
3387
|
+
* const value = yield* Metric.value(responseTimeHistogram)
|
|
3388
|
+
* return value
|
|
3389
|
+
* })
|
|
3390
|
+
* ```
|
|
3391
|
+
*
|
|
3392
|
+
* @category boundaries
|
|
3393
|
+
* @since 4.0.0
|
|
3394
|
+
*/
|
|
3395
|
+
export const linearBoundaries = (options: {
|
|
3396
|
+
readonly start: number
|
|
3397
|
+
readonly width: number
|
|
3398
|
+
readonly count: number
|
|
3399
|
+
}): ReadonlyArray<number> =>
|
|
3400
|
+
boundariesFromIterable(Arr.makeBy(options.count - 1, (n) => options.start + n + options.width))
|
|
3401
|
+
|
|
3402
|
+
/**
|
|
3403
|
+
* Creates histogram bucket boundaries with exponentially increasing values.
|
|
3404
|
+
*
|
|
3405
|
+
* **Details**
|
|
3406
|
+
*
|
|
3407
|
+
* Creates boundaries that grow exponentially, useful for metrics that span
|
|
3408
|
+
* multiple orders of magnitude. Each boundary is calculated as start * factor^i.
|
|
3409
|
+
*
|
|
3410
|
+
* **Example** (Creating exponential boundaries)
|
|
3411
|
+
*
|
|
3412
|
+
* ```ts
|
|
3413
|
+
* import { Data, Effect, Metric } from "effect"
|
|
3414
|
+
*
|
|
3415
|
+
* class BoundaryError extends Data.TaggedError("BoundaryError")<{
|
|
3416
|
+
* readonly operation: string
|
|
3417
|
+
* }> {}
|
|
3418
|
+
*
|
|
3419
|
+
* // Create exponential boundaries for request size histogram
|
|
3420
|
+
* // Buckets: 0-1KB, 1-2KB, 2-4KB, 4-8KB, 8KB+
|
|
3421
|
+
* const sizeBoundaries = Metric.exponentialBoundaries({
|
|
3422
|
+
* start: 1, // Starting at 1KB
|
|
3423
|
+
* factor: 2, // Each boundary doubles the previous
|
|
3424
|
+
* count: 5 // Creates 4 boundaries + infinity
|
|
3425
|
+
* })
|
|
3426
|
+
* console.log(sizeBoundaries) // [1, 2, 4, 8, Infinity]
|
|
3427
|
+
*
|
|
3428
|
+
* // Create a histogram for tracking request payload sizes
|
|
3429
|
+
* const requestSizeHistogram = Metric.histogram("request_size_kb", {
|
|
3430
|
+
* description: "Request payload size distribution in KB",
|
|
3431
|
+
* boundaries: sizeBoundaries
|
|
3432
|
+
* })
|
|
3433
|
+
*
|
|
3434
|
+
* // For very wide ranges, use larger factors
|
|
3435
|
+
* const latencyBoundaries = Metric.exponentialBoundaries({
|
|
3436
|
+
* start: 0.1, // Start at 0.1ms
|
|
3437
|
+
* factor: 10, // Each boundary is 10x larger
|
|
3438
|
+
* count: 6 // Creates ranges: 0.1ms, 1ms, 10ms, 100ms, 1000ms+
|
|
3439
|
+
* })
|
|
3440
|
+
*
|
|
3441
|
+
* const program = Effect.gen(function*() {
|
|
3442
|
+
* // Record different request sizes
|
|
3443
|
+
* yield* Metric.update(requestSizeHistogram, 1.5) // Goes in 1-2KB bucket
|
|
3444
|
+
* yield* Metric.update(requestSizeHistogram, 3.2) // Goes in 2-4KB bucket
|
|
3445
|
+
* yield* Metric.update(requestSizeHistogram, 12) // Goes in 8KB+ bucket
|
|
3446
|
+
*
|
|
3447
|
+
* const value = yield* Metric.value(requestSizeHistogram)
|
|
3448
|
+
* return value
|
|
3449
|
+
* })
|
|
3450
|
+
* ```
|
|
3451
|
+
*
|
|
3452
|
+
* @category boundaries
|
|
3453
|
+
* @since 4.0.0
|
|
3454
|
+
*/
|
|
3455
|
+
export const exponentialBoundaries = (options: {
|
|
3456
|
+
readonly start: number
|
|
3457
|
+
readonly factor: number
|
|
3458
|
+
readonly count: number
|
|
3459
|
+
}): ReadonlyArray<number> =>
|
|
3460
|
+
boundariesFromIterable(Arr.makeBy(options.count - 1, (i) => options.start * Math.pow(options.factor, i)))
|
|
3461
|
+
|
|
3462
|
+
// Fiber Runtime Metrics
|
|
3463
|
+
|
|
3464
|
+
const fibersActive = gauge("child_fibers_active", {
|
|
3465
|
+
description: "The current count of active child fibers"
|
|
3466
|
+
})
|
|
3467
|
+
const fibersStarted = counter("child_fibers_started", {
|
|
3468
|
+
description: "The total number of child fibers that have been started",
|
|
3469
|
+
incremental: true
|
|
3470
|
+
})
|
|
3471
|
+
const fiberSuccesses = counter("child_fiber_successes", {
|
|
3472
|
+
description: "The total number of child fibers that have succeeded",
|
|
3473
|
+
incremental: true
|
|
3474
|
+
})
|
|
3475
|
+
const fiberFailures = counter("child_fiber_failures", {
|
|
3476
|
+
description: "The total number of child fibers that have failed",
|
|
3477
|
+
incremental: true
|
|
3478
|
+
})
|
|
3479
|
+
|
|
3480
|
+
/**
|
|
3481
|
+
* Service key for the fiber runtime metrics service.
|
|
3482
|
+
*
|
|
3483
|
+
* **Example** (Accessing the fiber runtime metrics key)
|
|
3484
|
+
*
|
|
3485
|
+
* ```ts
|
|
3486
|
+
* import { Data, Effect, Layer, Metric } from "effect"
|
|
3487
|
+
*
|
|
3488
|
+
* class MetricsError extends Data.TaggedError("MetricsError")<{
|
|
3489
|
+
* readonly operation: string
|
|
3490
|
+
* }> {}
|
|
3491
|
+
*
|
|
3492
|
+
* const program = Effect.gen(function*() {
|
|
3493
|
+
* // The key is used internally by the Effect runtime to manage fiber metrics
|
|
3494
|
+
* const key = Metric.FiberRuntimeMetricsKey
|
|
3495
|
+
* console.log("Fiber metrics key:", key)
|
|
3496
|
+
*
|
|
3497
|
+
* // Enable runtime metrics using the key
|
|
3498
|
+
* const layer = Layer.succeed(Metric.FiberRuntimeMetrics)(
|
|
3499
|
+
* Metric.FiberRuntimeMetricsImpl
|
|
3500
|
+
* )
|
|
3501
|
+
*
|
|
3502
|
+
* return yield* Effect.gen(function*() {
|
|
3503
|
+
* // This Effect will have fiber metrics automatically collected
|
|
3504
|
+
* yield* Effect.sleep("100 millis")
|
|
3505
|
+
*
|
|
3506
|
+
* // Create a test counter to demonstrate the key usage
|
|
3507
|
+
* const testCounter = Metric.counter("test_counter")
|
|
3508
|
+
* yield* Metric.update(testCounter, 1)
|
|
3509
|
+
* return yield* Metric.value(testCounter)
|
|
3510
|
+
* }).pipe(Effect.provide(layer))
|
|
3511
|
+
* })
|
|
3512
|
+
* ```
|
|
3513
|
+
*
|
|
3514
|
+
* @category metrics
|
|
3515
|
+
* @since 4.0.0
|
|
3516
|
+
*/
|
|
3517
|
+
export const FiberRuntimeMetricsKey: "effect/observability/Metric/FiberRuntimeMetricsKey" =
|
|
3518
|
+
InternalMetric.FiberRuntimeMetricsKey
|
|
3519
|
+
|
|
3520
|
+
/**
|
|
3521
|
+
* Interface for the fiber runtime metrics service that tracks fiber lifecycle events.
|
|
3522
|
+
*
|
|
3523
|
+
* **Example** (Providing a custom fiber metrics service)
|
|
3524
|
+
*
|
|
3525
|
+
* ```ts
|
|
3526
|
+
* import { Data, Effect, Layer, Metric } from "effect"
|
|
3527
|
+
* import type { Context, Exit } from "effect"
|
|
3528
|
+
*
|
|
3529
|
+
* class MetricsError extends Data.TaggedError("MetricsError")<{
|
|
3530
|
+
* readonly operation: string
|
|
3531
|
+
* }> {}
|
|
3532
|
+
*
|
|
3533
|
+
* // Custom implementation of the metrics service
|
|
3534
|
+
* const customMetricsService: Metric.FiberRuntimeMetricsService = {
|
|
3535
|
+
* recordFiberStart: (context: Context.Context<never>) => {
|
|
3536
|
+
* console.log("Fiber started")
|
|
3537
|
+
* // Custom logic for tracking fiber starts
|
|
3538
|
+
* },
|
|
3539
|
+
* recordFiberEnd: (
|
|
3540
|
+
* context: Context.Context<never>,
|
|
3541
|
+
* exit: Exit.Exit<unknown, unknown>
|
|
3542
|
+
* ) => {
|
|
3543
|
+
* console.log("Fiber completed with exit:", exit)
|
|
3544
|
+
* // Custom logic for tracking fiber completion based on exit status
|
|
3545
|
+
* }
|
|
3546
|
+
* }
|
|
3547
|
+
*
|
|
3548
|
+
* const program = Effect.gen(function*() {
|
|
3549
|
+
* // Use the custom metrics service
|
|
3550
|
+
* const layer = Layer.succeed(Metric.FiberRuntimeMetrics)(customMetricsService)
|
|
3551
|
+
*
|
|
3552
|
+
* return yield* Effect.sleep("100 millis").pipe(Effect.provide(layer))
|
|
3553
|
+
* })
|
|
3554
|
+
* ```
|
|
3555
|
+
*
|
|
3556
|
+
* @category metrics
|
|
3557
|
+
* @since 4.0.0
|
|
3558
|
+
*/
|
|
3559
|
+
export interface FiberRuntimeMetricsService {
|
|
3560
|
+
readonly recordFiberStart: (context: Context.Context<never>) => void
|
|
3561
|
+
readonly recordFiberEnd: (context: Context.Context<never>, exit: Exit<unknown, unknown>) => void
|
|
3562
|
+
}
|
|
3563
|
+
|
|
3564
|
+
/**
|
|
3565
|
+
* Context reference for the optional service that records fiber runtime
|
|
3566
|
+
* metrics.
|
|
3567
|
+
*
|
|
3568
|
+
* **When to use**
|
|
3569
|
+
*
|
|
3570
|
+
* Use to provide or inspect the service that receives fiber start and end
|
|
3571
|
+
* notifications for automatic runtime metrics.
|
|
3572
|
+
*
|
|
3573
|
+
* **Details**
|
|
3574
|
+
*
|
|
3575
|
+
* When provided, the runtime can notify the service about child-fiber start and
|
|
3576
|
+
* end events. When the reference is `undefined`, automatic fiber runtime metric
|
|
3577
|
+
* collection is disabled.
|
|
3578
|
+
*
|
|
3579
|
+
* **Example** (Accessing the fiber runtime metrics service)
|
|
3580
|
+
*
|
|
3581
|
+
* ```ts
|
|
3582
|
+
* import { Data, Effect, Metric } from "effect"
|
|
3583
|
+
*
|
|
3584
|
+
* class MetricsError extends Data.TaggedError("MetricsError")<{
|
|
3585
|
+
* readonly operation: string
|
|
3586
|
+
* }> {}
|
|
3587
|
+
*
|
|
3588
|
+
* const program = Effect.gen(function*() {
|
|
3589
|
+
* // Access the fiber runtime metrics service
|
|
3590
|
+
* const metricsService = yield* Metric.FiberRuntimeMetrics
|
|
3591
|
+
*
|
|
3592
|
+
* if (metricsService) {
|
|
3593
|
+
* console.log("Runtime metrics are enabled")
|
|
3594
|
+
* } else {
|
|
3595
|
+
* console.log("Runtime metrics are disabled")
|
|
3596
|
+
* }
|
|
3597
|
+
*
|
|
3598
|
+
* // Enable runtime metrics for the application
|
|
3599
|
+
* const enabledLayer = Metric.enableRuntimeMetricsLayer
|
|
3600
|
+
*
|
|
3601
|
+
* return yield* Effect.gen(function*() {
|
|
3602
|
+
* // Create some concurrent fibers to see metrics in action
|
|
3603
|
+
* yield* Effect.all([
|
|
3604
|
+
* Effect.sleep("100 millis"),
|
|
3605
|
+
* Effect.sleep("200 millis"),
|
|
3606
|
+
* Effect.sleep("300 millis")
|
|
3607
|
+
* ], { concurrency: "unbounded" })
|
|
3608
|
+
*
|
|
3609
|
+
* // Create test metrics to demonstrate the service
|
|
3610
|
+
* const testCounter = Metric.counter("test_counter")
|
|
3611
|
+
* yield* Metric.update(testCounter, 5)
|
|
3612
|
+
* const counterValue = yield* Metric.value(testCounter)
|
|
3613
|
+
*
|
|
3614
|
+
* return { counterValue, metricsEnabled: true }
|
|
3615
|
+
* }).pipe(Effect.provide(enabledLayer))
|
|
3616
|
+
* })
|
|
3617
|
+
* ```
|
|
3618
|
+
*
|
|
3619
|
+
* @category runtime metrics
|
|
3620
|
+
* @since 4.0.0
|
|
3621
|
+
*/
|
|
3622
|
+
export const FiberRuntimeMetrics = Context.Reference<FiberRuntimeMetricsService | undefined>(
|
|
3623
|
+
InternalMetric.FiberRuntimeMetricsKey,
|
|
3624
|
+
{ defaultValue: constUndefined }
|
|
3625
|
+
)
|
|
3626
|
+
|
|
3627
|
+
/**
|
|
3628
|
+
* Default implementation of the fiber runtime metrics service.
|
|
3629
|
+
*
|
|
3630
|
+
* **Example** (Accessing the default fiber metrics implementation)
|
|
3631
|
+
*
|
|
3632
|
+
* ```ts
|
|
3633
|
+
* import { Data, Effect, Layer, Metric } from "effect"
|
|
3634
|
+
*
|
|
3635
|
+
* class MetricsError extends Data.TaggedError("MetricsError")<{
|
|
3636
|
+
* readonly operation: string
|
|
3637
|
+
* }> {}
|
|
3638
|
+
*
|
|
3639
|
+
* const program = Effect.gen(function*() {
|
|
3640
|
+
* // Use the default metrics implementation
|
|
3641
|
+
* const metrics = Metric.FiberRuntimeMetricsImpl
|
|
3642
|
+
* console.log("Metrics implementation:", metrics)
|
|
3643
|
+
*
|
|
3644
|
+
* // Enable runtime metrics using the default implementation
|
|
3645
|
+
* const layer = Layer.succeed(Metric.FiberRuntimeMetrics)(metrics)
|
|
3646
|
+
*
|
|
3647
|
+
* return yield* Effect.gen(function*() {
|
|
3648
|
+
* // Run some Effects to trigger metric collection
|
|
3649
|
+
* yield* Effect.forkChild(Effect.sleep("50 millis"))
|
|
3650
|
+
* yield* Effect.forkChild(Effect.sleep("100 millis"))
|
|
3651
|
+
*
|
|
3652
|
+
* // Wait a bit and check the metrics
|
|
3653
|
+
* yield* Effect.sleep("200 millis")
|
|
3654
|
+
*
|
|
3655
|
+
* // Create test metrics to demonstrate the implementation
|
|
3656
|
+
* const testCounter = Metric.counter("test_counter")
|
|
3657
|
+
* const testGauge = Metric.gauge("test_gauge")
|
|
3658
|
+
* yield* Metric.update(testCounter, 3)
|
|
3659
|
+
* yield* Metric.update(testGauge, 42)
|
|
3660
|
+
*
|
|
3661
|
+
* const counterValue = yield* Metric.value(testCounter)
|
|
3662
|
+
* const gaugeValue = yield* Metric.value(testGauge)
|
|
3663
|
+
*
|
|
3664
|
+
* return { counter: counterValue, gauge: gaugeValue }
|
|
3665
|
+
* }).pipe(Effect.provide(layer))
|
|
3666
|
+
* })
|
|
3667
|
+
* ```
|
|
3668
|
+
*
|
|
3669
|
+
* @category metrics
|
|
3670
|
+
* @since 4.0.0
|
|
3671
|
+
*/
|
|
3672
|
+
export const FiberRuntimeMetricsImpl: FiberRuntimeMetricsService = {
|
|
3673
|
+
recordFiberStart(context: Context.Context<never>) {
|
|
3674
|
+
fibersStarted.updateUnsafe(1, context)
|
|
3675
|
+
fibersActive.modifyUnsafe(1, context)
|
|
3676
|
+
},
|
|
3677
|
+
recordFiberEnd(context: Context.Context<never>, exit: Exit<unknown, unknown>) {
|
|
3678
|
+
fibersActive.modifyUnsafe(-1, context)
|
|
3679
|
+
if (InternalEffect.exitIsSuccess(exit)) {
|
|
3680
|
+
fiberSuccesses.updateUnsafe(1, context)
|
|
3681
|
+
} else {
|
|
3682
|
+
fiberFailures.updateUnsafe(1, context)
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
|
|
3687
|
+
/**
|
|
3688
|
+
* Layer that enables automatic collection of fiber runtime metrics across
|
|
3689
|
+
* an entire Effect application.
|
|
3690
|
+
*
|
|
3691
|
+
* **When to use**
|
|
3692
|
+
*
|
|
3693
|
+
* Use when you need runtime metrics collection for all Effects in the
|
|
3694
|
+
* application context rather than wrapping individual Effects.
|
|
3695
|
+
*
|
|
3696
|
+
* **Example** (Enabling runtime metrics with a layer)
|
|
3697
|
+
*
|
|
3698
|
+
* ```ts
|
|
3699
|
+
* import { Console, Data, Effect, Layer, Metric } from "effect"
|
|
3700
|
+
*
|
|
3701
|
+
* class AppError extends Data.TaggedError("AppError")<{
|
|
3702
|
+
* readonly operation: string
|
|
3703
|
+
* }> {}
|
|
3704
|
+
*
|
|
3705
|
+
* // Define your application logic
|
|
3706
|
+
* const userService = Effect.gen(function*() {
|
|
3707
|
+
* // Simulate user operations with concurrent processing
|
|
3708
|
+
* const fetchUser = (id: number) =>
|
|
3709
|
+
* Effect.gen(function*() {
|
|
3710
|
+
* yield* Effect.sleep(`${50 + id * 10} millis`)
|
|
3711
|
+
* if (id % 7 === 0) {
|
|
3712
|
+
* return yield* new AppError({ operation: `fetch-user-${id}` })
|
|
3713
|
+
* }
|
|
3714
|
+
* return { id, name: `User ${id}`, email: `user${id}@example.com` }
|
|
3715
|
+
* })
|
|
3716
|
+
*
|
|
3717
|
+
* // Process multiple users concurrently (ignoring failures for demo)
|
|
3718
|
+
* const userIds = Array.from({ length: 10 }, (_, i) => i + 1)
|
|
3719
|
+
* const userTasks = userIds.map((id) =>
|
|
3720
|
+
* fetchUser(id).pipe(Effect.catchTag("AppError", () => Effect.succeed(null)))
|
|
3721
|
+
* )
|
|
3722
|
+
* const allUsers = yield* Effect.all(userTasks, { concurrency: 4 })
|
|
3723
|
+
* const successfulUsers = allUsers.filter((user) => user !== null)
|
|
3724
|
+
* return successfulUsers
|
|
3725
|
+
* })
|
|
3726
|
+
*
|
|
3727
|
+
* const analyticsService = Effect.gen(function*() {
|
|
3728
|
+
* // Simulate analytics processing
|
|
3729
|
+
* const tasks = Array.from({ length: 8 }, (_, i) =>
|
|
3730
|
+
* Effect.gen(function*() {
|
|
3731
|
+
* yield* Effect.sleep(`${100 + i * 25} millis`)
|
|
3732
|
+
* return `Analytics task ${i} completed`
|
|
3733
|
+
* }))
|
|
3734
|
+
* return yield* Effect.all(tasks, { concurrency: 3 })
|
|
3735
|
+
* })
|
|
3736
|
+
*
|
|
3737
|
+
* // Main application that uses multiple services
|
|
3738
|
+
* const application = Effect.gen(function*() {
|
|
3739
|
+
* yield* Console.log("Starting application with runtime metrics...")
|
|
3740
|
+
*
|
|
3741
|
+
* // Run services concurrently
|
|
3742
|
+
* const [users, analytics] = yield* Effect.all([
|
|
3743
|
+
* userService,
|
|
3744
|
+
* analyticsService
|
|
3745
|
+
* ], { concurrency: 2 })
|
|
3746
|
+
*
|
|
3747
|
+
* yield* Console.log(
|
|
3748
|
+
* `Processed ${users.length} users and ${analytics.length} analytics tasks`
|
|
3749
|
+
* )
|
|
3750
|
+
*
|
|
3751
|
+
* // Inspect the automatically collected runtime metrics
|
|
3752
|
+
* const metrics = yield* Metric.snapshot
|
|
3753
|
+
* const runtimeMetrics = metrics.filter((m) => m.id.startsWith("child_fiber"))
|
|
3754
|
+
*
|
|
3755
|
+
* yield* Console.log("Runtime Metrics Collected:")
|
|
3756
|
+
* for (const metric of runtimeMetrics) {
|
|
3757
|
+
* yield* Console.log(` ${metric.id}: ${JSON.stringify(metric.state)}`)
|
|
3758
|
+
* }
|
|
3759
|
+
*
|
|
3760
|
+
* return { users, analytics, metricsCount: runtimeMetrics.length }
|
|
3761
|
+
* })
|
|
3762
|
+
*
|
|
3763
|
+
* // Create the base application layer
|
|
3764
|
+
* const AppLayer = Layer.empty // Add your application layers here (database, HTTP, etc.)
|
|
3765
|
+
*
|
|
3766
|
+
* // Add runtime metrics layer at the end
|
|
3767
|
+
* const AppLayerWithMetrics = AppLayer.pipe(
|
|
3768
|
+
* Layer.provide(Metric.enableRuntimeMetricsLayer)
|
|
3769
|
+
* )
|
|
3770
|
+
*
|
|
3771
|
+
* // Run the application with runtime metrics enabled
|
|
3772
|
+
* const program = application.pipe(
|
|
3773
|
+
* Effect.provide(AppLayerWithMetrics)
|
|
3774
|
+
* )
|
|
3775
|
+
*
|
|
3776
|
+
* // Alternative: Provide runtime metrics directly to the application
|
|
3777
|
+
* const programWithDirectMetrics = application.pipe(
|
|
3778
|
+
* Effect.provide(Metric.enableRuntimeMetricsLayer)
|
|
3779
|
+
* )
|
|
3780
|
+
* ```
|
|
3781
|
+
*
|
|
3782
|
+
* @category metrics
|
|
3783
|
+
* @since 4.0.0
|
|
3784
|
+
*/
|
|
3785
|
+
export const enableRuntimeMetricsLayer = Layer.succeed(FiberRuntimeMetrics)(FiberRuntimeMetricsImpl)
|
|
3786
|
+
|
|
3787
|
+
/**
|
|
3788
|
+
* Layer that disables automatic collection of fiber runtime metrics.
|
|
3789
|
+
*
|
|
3790
|
+
* **Example** (Disabling runtime metrics with a layer)
|
|
3791
|
+
*
|
|
3792
|
+
* ```ts
|
|
3793
|
+
* import { Data, Effect, Metric } from "effect"
|
|
3794
|
+
*
|
|
3795
|
+
* class MetricsError extends Data.TaggedError("MetricsError")<{
|
|
3796
|
+
* readonly operation: string
|
|
3797
|
+
* }> {}
|
|
3798
|
+
*
|
|
3799
|
+
* const program = Effect.gen(function*() {
|
|
3800
|
+
* // Disable runtime metrics collection
|
|
3801
|
+
* const disabledLayer = Metric.disableRuntimeMetricsLayer
|
|
3802
|
+
*
|
|
3803
|
+
* return yield* Effect.gen(function*() {
|
|
3804
|
+
* // Check that metrics service is disabled
|
|
3805
|
+
* const metricsService = yield* Metric.FiberRuntimeMetrics
|
|
3806
|
+
* console.log("Metrics enabled:", metricsService !== undefined) // false
|
|
3807
|
+
*
|
|
3808
|
+
* // Run some Effects - no metrics will be collected
|
|
3809
|
+
* yield* Effect.forkChild(Effect.sleep("50 millis"))
|
|
3810
|
+
* yield* Effect.forkChild(Effect.sleep("100 millis"))
|
|
3811
|
+
* yield* Effect.sleep("200 millis")
|
|
3812
|
+
*
|
|
3813
|
+
* // Create test metrics to show they still work
|
|
3814
|
+
* const testCounter = Metric.counter("test_counter")
|
|
3815
|
+
* yield* Metric.update(testCounter, 1)
|
|
3816
|
+
* const counterValue = yield* Metric.value(testCounter)
|
|
3817
|
+
*
|
|
3818
|
+
* return { counterValue, metricsEnabled: metricsService !== undefined }
|
|
3819
|
+
* }).pipe(Effect.provide(disabledLayer))
|
|
3820
|
+
* })
|
|
3821
|
+
* ```
|
|
3822
|
+
*
|
|
3823
|
+
* @category metrics
|
|
3824
|
+
* @since 4.0.0
|
|
3825
|
+
*/
|
|
3826
|
+
export const disableRuntimeMetricsLayer = Layer.succeed(FiberRuntimeMetrics)(undefined)
|
|
3827
|
+
|
|
3828
|
+
/**
|
|
3829
|
+
* Enables automatic collection of fiber runtime metrics for the provided Effect.
|
|
3830
|
+
*
|
|
3831
|
+
* **Details**
|
|
3832
|
+
*
|
|
3833
|
+
* When enabled, automatically tracks fiber lifecycle metrics including active fibers,
|
|
3834
|
+
* started fibers, successful completions, and failures. These metrics provide valuable
|
|
3835
|
+
* insights into the concurrency patterns and health of your Effect application.
|
|
3836
|
+
*
|
|
3837
|
+
* **Example** (Enabling runtime metrics for an effect)
|
|
3838
|
+
*
|
|
3839
|
+
* ```ts
|
|
3840
|
+
* import { Console, Data, Effect, Layer, Metric } from "effect"
|
|
3841
|
+
*
|
|
3842
|
+
* class RuntimeMetricsError extends Data.TaggedError("RuntimeMetricsError")<{
|
|
3843
|
+
* readonly operation: string
|
|
3844
|
+
* }> {}
|
|
3845
|
+
*
|
|
3846
|
+
* const program = Effect.gen(function*() {
|
|
3847
|
+
* // Create a concurrent workload to demonstrate fiber metrics
|
|
3848
|
+
* const heavyWorkload = Effect.gen(function*() {
|
|
3849
|
+
* // Simulate concurrent operations
|
|
3850
|
+
* const tasks = Array.from({ length: 10 }, (_, i) =>
|
|
3851
|
+
* Effect.gen(function*() {
|
|
3852
|
+
* yield* Effect.sleep(`${100 + i * 50} millis`)
|
|
3853
|
+
* if (i % 4 === 0) {
|
|
3854
|
+
* // Simulate some failures
|
|
3855
|
+
* return yield* new RuntimeMetricsError({ operation: `task-${i}` })
|
|
3856
|
+
* }
|
|
3857
|
+
* return `Task ${i} completed`
|
|
3858
|
+
* }).pipe(
|
|
3859
|
+
* Effect.catchTag("RuntimeMetricsError", () =>
|
|
3860
|
+
* Effect.succeed(`Task ${i} failed`))
|
|
3861
|
+
* ))
|
|
3862
|
+
*
|
|
3863
|
+
* // Run tasks concurrently
|
|
3864
|
+
* const results = yield* Effect.all(tasks, { concurrency: 5 })
|
|
3865
|
+
* return results
|
|
3866
|
+
* })
|
|
3867
|
+
*
|
|
3868
|
+
* // Enable runtime metrics collection for our workload
|
|
3869
|
+
* const workloadWithMetrics = Metric.enableRuntimeMetrics(heavyWorkload)
|
|
3870
|
+
*
|
|
3871
|
+
* // Execute the workload
|
|
3872
|
+
* const results = yield* workloadWithMetrics
|
|
3873
|
+
*
|
|
3874
|
+
* // After execution, we can inspect the runtime metrics
|
|
3875
|
+
* // The following metrics are automatically collected:
|
|
3876
|
+
* // - child_fibers_active: Current number of active child fibers (Gauge)
|
|
3877
|
+
* // - child_fibers_started: Total child fibers started (Counter, incremental)
|
|
3878
|
+
* // - child_fiber_successes: Total successful child fibers (Counter, incremental)
|
|
3879
|
+
* // - child_fiber_failures: Total failed child fibers (Counter, incremental)
|
|
3880
|
+
*
|
|
3881
|
+
* yield* Console.log(`Workload completed with ${results.length} results`)
|
|
3882
|
+
*
|
|
3883
|
+
* // Get all metrics including the runtime metrics
|
|
3884
|
+
* const allMetrics = yield* Metric.snapshot
|
|
3885
|
+
* const runtimeMetrics = allMetrics.filter((m) =>
|
|
3886
|
+
* m.id.startsWith("child_fiber") || m.id.includes("fiber")
|
|
3887
|
+
* )
|
|
3888
|
+
*
|
|
3889
|
+
* yield* Console.log("Runtime Metrics:")
|
|
3890
|
+
* for (const metric of runtimeMetrics) {
|
|
3891
|
+
* yield* Console.log(` ${metric.id}: ${JSON.stringify(metric.state)}`)
|
|
3892
|
+
* }
|
|
3893
|
+
*
|
|
3894
|
+
* return results
|
|
3895
|
+
* })
|
|
3896
|
+
*
|
|
3897
|
+
* // Alternative: Use the layer version for broader application coverage
|
|
3898
|
+
* const BaseAppLayer = Layer.empty // Your base application layers
|
|
3899
|
+
* const AppLayerWithMetrics = BaseAppLayer.pipe(
|
|
3900
|
+
* Layer.provide(Metric.enableRuntimeMetricsLayer)
|
|
3901
|
+
* )
|
|
3902
|
+
* const programWithLayer = program.pipe(
|
|
3903
|
+
* Effect.provide(AppLayerWithMetrics)
|
|
3904
|
+
* )
|
|
3905
|
+
* ```
|
|
3906
|
+
*
|
|
3907
|
+
* @category metrics
|
|
3908
|
+
* @since 4.0.0
|
|
3909
|
+
*/
|
|
3910
|
+
export const enableRuntimeMetrics: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R> = InternalEffect.provideService(
|
|
3911
|
+
FiberRuntimeMetrics,
|
|
3912
|
+
FiberRuntimeMetricsImpl
|
|
3913
|
+
)
|
|
3914
|
+
|
|
3915
|
+
/**
|
|
3916
|
+
* Disables automatic collection of fiber runtime metrics for the provided Effect.
|
|
3917
|
+
*
|
|
3918
|
+
* **When to use**
|
|
3919
|
+
*
|
|
3920
|
+
* Use when you need to disable runtime metrics for a specific effect while
|
|
3921
|
+
* keeping them enabled elsewhere.
|
|
3922
|
+
*
|
|
3923
|
+
* **Example** (Disabling runtime metrics for an effect)
|
|
3924
|
+
*
|
|
3925
|
+
* ```ts
|
|
3926
|
+
* import { Console, Data, Effect, Layer, Metric } from "effect"
|
|
3927
|
+
*
|
|
3928
|
+
* class DisableMetricsError extends Data.TaggedError("DisableMetricsError")<{
|
|
3929
|
+
* readonly operation: string
|
|
3930
|
+
* }> {}
|
|
3931
|
+
*
|
|
3932
|
+
* const program = Effect.gen(function*() {
|
|
3933
|
+
* // This section will have runtime metrics enabled
|
|
3934
|
+
* const normalOperation = Effect.gen(function*() {
|
|
3935
|
+
* const tasks = Array.from({ length: 5 }, (_, i) =>
|
|
3936
|
+
* Effect.gen(function*() {
|
|
3937
|
+
* yield* Effect.sleep(`${100 + i * 20} millis`)
|
|
3938
|
+
* return `Normal task ${i} completed`
|
|
3939
|
+
* }))
|
|
3940
|
+
* return yield* Effect.all(tasks, { concurrency: 3 })
|
|
3941
|
+
* })
|
|
3942
|
+
*
|
|
3943
|
+
* // This section will have runtime metrics disabled for performance
|
|
3944
|
+
* const highPerformanceOperation = Metric.disableRuntimeMetrics(
|
|
3945
|
+
* Effect.gen(function*() {
|
|
3946
|
+
* // Performance-critical code where metrics overhead should be avoided
|
|
3947
|
+
* const hotPath = Array.from(
|
|
3948
|
+
* { length: 1000 },
|
|
3949
|
+
* (_, i) =>
|
|
3950
|
+
* Effect.gen(function*() {
|
|
3951
|
+
* // Simulate intensive computation
|
|
3952
|
+
* const result = i * i + (i % 10) / 10
|
|
3953
|
+
* return result
|
|
3954
|
+
* })
|
|
3955
|
+
* )
|
|
3956
|
+
* return yield* Effect.all(hotPath, { concurrency: 100 })
|
|
3957
|
+
* })
|
|
3958
|
+
* )
|
|
3959
|
+
*
|
|
3960
|
+
* yield* Console.log("Running operations with selective metrics...")
|
|
3961
|
+
*
|
|
3962
|
+
* // Run both operations
|
|
3963
|
+
* const [normalResults, performanceResults] = yield* Effect.all([
|
|
3964
|
+
* normalOperation, // Will generate fiber metrics
|
|
3965
|
+
* highPerformanceOperation // Will NOT generate fiber metrics
|
|
3966
|
+
* ])
|
|
3967
|
+
*
|
|
3968
|
+
* // Check collected metrics - should only see metrics from normalOperation
|
|
3969
|
+
* const metrics = yield* Metric.snapshot
|
|
3970
|
+
* const runtimeMetrics = metrics.filter((m) => m.id.startsWith("child_fiber"))
|
|
3971
|
+
*
|
|
3972
|
+
* yield* Console.log(`Normal operation results: ${normalResults.length}`)
|
|
3973
|
+
* yield* Console.log(
|
|
3974
|
+
* `Performance operation results: ${performanceResults.length}`
|
|
3975
|
+
* )
|
|
3976
|
+
* yield* Console.log(`Runtime metrics collected: ${runtimeMetrics.length}`)
|
|
3977
|
+
*
|
|
3978
|
+
* // The runtime metrics will only reflect the fibers from normalOperation
|
|
3979
|
+
* // The highPerformanceOperation fibers were not tracked due to disableRuntimeMetrics
|
|
3980
|
+
*
|
|
3981
|
+
* return { normalResults, performanceResults, runtimeMetrics }
|
|
3982
|
+
* })
|
|
3983
|
+
*
|
|
3984
|
+
* // Enable runtime metrics globally, then selectively disable where needed
|
|
3985
|
+
* const BaseAppLayer = Layer.empty // Your base application layers
|
|
3986
|
+
* const AppLayerWithMetrics = BaseAppLayer.pipe(
|
|
3987
|
+
* Layer.provide(Metric.enableRuntimeMetricsLayer)
|
|
3988
|
+
* )
|
|
3989
|
+
* const finalProgram = program.pipe(
|
|
3990
|
+
* Effect.provide(AppLayerWithMetrics)
|
|
3991
|
+
* )
|
|
3992
|
+
* ```
|
|
3993
|
+
*
|
|
3994
|
+
* @category metrics
|
|
3995
|
+
* @since 4.0.0
|
|
3996
|
+
*/
|
|
3997
|
+
export const disableRuntimeMetrics: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R> = InternalEffect.provideService(
|
|
3998
|
+
FiberRuntimeMetrics,
|
|
3999
|
+
undefined
|
|
4000
|
+
)
|
|
4001
|
+
|
|
4002
|
+
// Utilities
|
|
4003
|
+
|
|
4004
|
+
function makeKey<Input, State>(
|
|
4005
|
+
metric: Metric<Input, State>,
|
|
4006
|
+
attributes: Metric.Attributes | undefined
|
|
4007
|
+
) {
|
|
4008
|
+
let key = `${metric.type}:${metric.id}`
|
|
4009
|
+
if (Predicate.isNotUndefined(metric.description)) {
|
|
4010
|
+
key += `:${metric.description}`
|
|
4011
|
+
}
|
|
4012
|
+
if (Predicate.isNotUndefined(attributes)) {
|
|
4013
|
+
key += `:${serializeAttributes(attributes)}`
|
|
4014
|
+
}
|
|
4015
|
+
return key
|
|
4016
|
+
}
|
|
4017
|
+
|
|
4018
|
+
function makeHooks<Input, State>(
|
|
4019
|
+
get: (context: Context.Context<never>) => State,
|
|
4020
|
+
update: (input: Input, context: Context.Context<never>) => void,
|
|
4021
|
+
modify?: (input: Input, context: Context.Context<never>) => void
|
|
4022
|
+
): Metric.Hooks<Input, State> {
|
|
4023
|
+
return { get, update, modify: modify ?? update }
|
|
4024
|
+
}
|
|
4025
|
+
|
|
4026
|
+
function serializeAttributes(attributes: Metric.Attributes): string {
|
|
4027
|
+
return serializeEntries(Array.isArray(attributes) ? attributes : Object.entries(attributes))
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
function serializeEntries(entries: ReadonlyArray<[string, string]>): string {
|
|
4031
|
+
return entries.map(([key, value]) => `${key}=${value}`).join(",")
|
|
4032
|
+
}
|
|
4033
|
+
|
|
4034
|
+
function mergeAttributes(
|
|
4035
|
+
self: Metric.Attributes | undefined,
|
|
4036
|
+
other: Metric.Attributes | undefined
|
|
4037
|
+
): Metric.AttributeSet {
|
|
4038
|
+
return { ...attributesToRecord(self), ...attributesToRecord(other) }
|
|
4039
|
+
}
|
|
4040
|
+
|
|
4041
|
+
function attributesToRecord(attributes?: Metric.Attributes): Metric.AttributeSet | undefined {
|
|
4042
|
+
if (Predicate.isNotUndefined(attributes) && Array.isArray(attributes)) {
|
|
4043
|
+
return attributes.reduce((acc, [key, value]) => {
|
|
4044
|
+
acc[key] = value
|
|
4045
|
+
return acc
|
|
4046
|
+
}, {} as Metric.AttributeSet)
|
|
4047
|
+
}
|
|
4048
|
+
return attributes as Metric.AttributeSet | undefined
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4051
|
+
function addAttributesToContext(
|
|
4052
|
+
context: Context.Context<never>,
|
|
4053
|
+
attributes: Metric.Attributes
|
|
4054
|
+
): Context.Context<never> {
|
|
4055
|
+
const current = Context.get(context, CurrentMetricAttributes)
|
|
4056
|
+
const updated = mergeAttributes(current, attributes)
|
|
4057
|
+
return Context.add(context, CurrentMetricAttributes, updated)
|
|
4058
|
+
}
|