diff --git a/examples/roll_dice_elli/.gitignore b/examples/roll_dice_elli/.gitignore new file mode 100644 index 0000000..cb13f5f --- /dev/null +++ b/examples/roll_dice_elli/.gitignore @@ -0,0 +1,21 @@ +.rebar3 +_* +.eunit +*.o +*.beam +*.plt +*.swp +*.swo +.erlang.cookie +ebin +log +erl_crash.dump +.rebar +logs +_build +.idea +*.iml +rebar3.crashdump +*~ +node_modules +priv/static/index.js \ No newline at end of file diff --git a/examples/roll_dice_elli/LICENSE b/examples/roll_dice_elli/LICENSE new file mode 100644 index 0000000..f5a9482 --- /dev/null +++ b/examples/roll_dice_elli/LICENSE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2023, Tristan Sloughter . + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/examples/roll_dice_elli/README.md b/examples/roll_dice_elli/README.md new file mode 100644 index 0000000..cab7c2c --- /dev/null +++ b/examples/roll_dice_elli/README.md @@ -0,0 +1,17 @@ +roll_dice +===== + +Run the project: + +``` +$ OTEL_EXPORTER_OTLP_PROTOCOL=grpc OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 rebar3 shell +``` + +Roll a die: + +``` +$ curl localhost:3000/rolldice +4 +``` + +Or go to `localhost:3000` in a browser to roll. diff --git a/examples/roll_dice_elli/config/sys.config b/examples/roll_dice_elli/config/sys.config new file mode 100644 index 0000000..a547ae4 --- /dev/null +++ b/examples/roll_dice_elli/config/sys.config @@ -0,0 +1,16 @@ +[ + {roll_dice, []}, + + {opentelemetry_elli, [{excluded_paths, ["/static", "/favicon.ico"]}]}, + + {opentelemetry_experimental, + [{readers, [#{module => otel_metric_reader, + config => #{export_interval_ms => 1000, + exporter => {opentelemetry_exporter, #{}}}}]}]}, + + {kernel, + [{logger_level, debug}, + {logger, + [{handler, default, logger_std_h, + #{formatter => {logger_formatter, #{}}}}]}]} +]. diff --git a/examples/roll_dice_elli/config/vm.args b/examples/roll_dice_elli/config/vm.args new file mode 100644 index 0000000..d8d8969 --- /dev/null +++ b/examples/roll_dice_elli/config/vm.args @@ -0,0 +1,3 @@ +-name roll_dice@127.0.0.1 + +-setcookie roll_dice_cookie diff --git a/examples/roll_dice_elli/docker-compose.yml b/examples/roll_dice_elli/docker-compose.yml new file mode 100644 index 0000000..ed5d785 --- /dev/null +++ b/examples/roll_dice_elli/docker-compose.yml @@ -0,0 +1,23 @@ +version: "3" +services: + otel: + image: otel/opentelemetry-collector-contrib:0.76.1 + command: ["--config=/conf/otel-collector-config.yaml"] + privileged: true + ports: + - 4317:4317 + - 4318:4318 + - 55679:55679 + volumes: + - ./otel-collector-config.yaml:/conf/otel-collector-config.yaml + links: + - jaeger-all-in-one + + jaeger-all-in-one: + image: jaegertracing/all-in-one:1.45 + restart: always + environment: + COLLECTOR_OTLP_ENABLED: true + ports: + - "16686:16686" + - "4317" diff --git a/examples/roll_dice_elli/js/app.js b/examples/roll_dice_elli/js/app.js new file mode 100644 index 0000000..232bd94 --- /dev/null +++ b/examples/roll_dice_elli/js/app.js @@ -0,0 +1,40 @@ +import 'htmx.org'; +import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; +import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request'; +import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load'; +import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; +import { ZoneContextManager } from '@opentelemetry/context-zone'; +import { Resource } from '@opentelemetry/resources'; +import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; +import * as api from '@opentelemetry/api'; + +const providerWithZone = new WebTracerProvider({ + resource: new Resource({ + [SemanticResourceAttributes.SERVICE_NAME]: 'roll-dice-ui', + }), +}); + +providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); +providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter({ + url: "http://localhost:4318/v1/traces" +}))); + +providerWithZone.register({ + contextManager: new ZoneContextManager() +}); + +registerInstrumentations({ + instrumentations: [ + new DocumentLoadInstrumentation(), + new XMLHttpRequestInstrumentation({ + ignoreUrls: [/localhost/], + propagateTraceHeaderCorsUrls: [ + 'http://localhost:3000', + ], + }), + ], + tracerProvider: providerWithZone, +}); + diff --git a/examples/roll_dice_elli/otel-collector-config.yaml b/examples/roll_dice_elli/otel-collector-config.yaml new file mode 100644 index 0000000..f69b3c6 --- /dev/null +++ b/examples/roll_dice_elli/otel-collector-config.yaml @@ -0,0 +1,44 @@ +# OpenTelemetry Collector config that receives OTLP and exports to Zipkin +receivers: + otlp: + protocols: + grpc: + endpoint: "0.0.0.0:4317" + http: + cors: + allowed_origins: + - "http://localhost:3000" + endpoint: "0.0.0.0:4318" +processors: + batch: + send_batch_size: 1024 + timeout: 5s +exporters: + otlp: + endpoint: jaeger-all-in-one:4317 + tls: + insecure: true + + logging: + loglevel: debug + sampling_initial: 1 + sampling_thereafter: 1 + +service: + telemetry: + logs: + level: "debug" + extensions: [zpages] + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [logging, otlp] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [logging] + logs: + receivers: [otlp] + processors: [batch] + exporters: [logging] diff --git a/examples/roll_dice_elli/package-lock.json b/examples/roll_dice_elli/package-lock.json new file mode 100644 index 0000000..73af200 --- /dev/null +++ b/examples/roll_dice_elli/package-lock.json @@ -0,0 +1,857 @@ +{ + "name": "roll_dice", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@opentelemetry/api": "^1.4.1", + "@opentelemetry/auto-instrumentations-web": "^0.32.2", + "@opentelemetry/context-zone": "^1.13.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.39.1", + "@opentelemetry/exporter-zipkin": "^1.13.0", + "@opentelemetry/instrumentation-document-load": "^0.32.2", + "@opentelemetry/sdk-trace-web": "^1.13.0", + "esbuild": "0.17.19", + "htmx.org": "^1.9.2" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.4.1.tgz", + "integrity": "sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.39.1.tgz", + "integrity": "sha512-9BJ8lMcOzEN0lu+Qji801y707oFO4xT3db6cosPvl+k7ItUHKN5ofWqtSbM9gbt1H4JJ/4/2TVrqI9Rq7hNv6Q==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-web": { + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-web/-/auto-instrumentations-web-0.32.2.tgz", + "integrity": "sha512-50Fv0omhhaReBPnuh+apTT+RVLXjpEJQIzn26650VnPdBqCkbSzxmXFsMOqDKrrGpSchwZKD/7BU9GeIUDSgPA==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.39.1", + "@opentelemetry/instrumentation-document-load": "^0.32.2", + "@opentelemetry/instrumentation-fetch": "^0.39.1", + "@opentelemetry/instrumentation-user-interaction": "^0.32.3", + "@opentelemetry/instrumentation-xml-http-request": "^0.39.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/context-zone": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-zone/-/context-zone-1.13.0.tgz", + "integrity": "sha512-lgzSIy2XyCUHNW2LrAwv/RHzIou5uf29flmJzH9P6S5ikql9CX5o3vcUOimOQxpRSZXWU24puV4hIWhtYTWGZg==", + "dependencies": { + "@opentelemetry/context-zone-peer-dep": "1.13.0", + "zone.js": "^0.11.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-zone-peer-dep": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-zone-peer-dep/-/context-zone-peer-dep-1.13.0.tgz", + "integrity": "sha512-fog8gIaVum2+WT2z9e3BIdfzekiePBcra2yzHpIz8gNpqirU0O4UNedDJWGJayAdutDU0W8Tx6V4HcTUKwhA8A==", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.5.0", + "zone.js": "^0.10.2 || ^0.11.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.13.0.tgz", + "integrity": "sha512-2dBX3Sj99H96uwJKvc2w9NOiNgbvAO6mOFJFramNkKfS9O4Um+VWgpnlAazoYjT6kUJ1MP70KQ5ngD4ed+4NUw==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.5.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.39.1.tgz", + "integrity": "sha512-AEhnJfVmo1g+7NxszAuf3c6vddld2DGH2+IM4XrPxCklucCsIpuStuC5EVZbCXXXBMpAY+n3t04QMxIQqNrcSw==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/otlp-exporter-base": "0.39.1", + "@opentelemetry/otlp-transformer": "0.39.1", + "@opentelemetry/resources": "1.13.0", + "@opentelemetry/sdk-trace-base": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.13.0.tgz", + "integrity": "sha512-4IuUmYEhlHm8tAGtd6KKkktEO9Bt7dpdBdAPVAzhmXsPwGi0yExo7E5qfi9HtHQcdfP9SnrGRkeorVtrZkGlhg==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/resources": "1.13.0", + "@opentelemetry/sdk-trace-base": "1.13.0", + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.39.1.tgz", + "integrity": "sha512-s7/9tPmM0l5KCd07VQizC4AO2/5UJdkXq5gMSHPdCeiMKSeBEdyDyQX7A+Cq+RYZM452qzFmrJ4ut628J5bnSg==", + "dependencies": { + "require-in-the-middle": "^7.1.0", + "semver": "^7.3.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-document-load": { + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-document-load/-/instrumentation-document-load-0.32.2.tgz", + "integrity": "sha512-j5klJHCz3HXbhl3nOJK3qMQkWXWcNUtGaaEcYh3uD1VdzvC6+SGbp40FGAGZXAhnlkIcWyTDsPGsNI1c0KuzNw==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.39.1", + "@opentelemetry/sdk-trace-base": "^1.0.0", + "@opentelemetry/sdk-trace-web": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fetch": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fetch/-/instrumentation-fetch-0.39.1.tgz", + "integrity": "sha512-JuIzMq/c/7EUFMuARJDBrAQCE4cwTCAmBQzQmALP4JbomyJ4Sax7nSYA+3QZ4x8m9fpsIaFtA0+45hn16/HEKQ==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/instrumentation": "0.39.1", + "@opentelemetry/sdk-trace-web": "1.13.0", + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation-user-interaction": { + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-user-interaction/-/instrumentation-user-interaction-0.32.3.tgz", + "integrity": "sha512-Hf4PVmjEQ3fWLfHrYwO2VP9Wr5bWPl3b6UrGqwnqFkrE7/OvsW9R10vMjHxZxORBGGLE7we+ROfJMpwDWNVdvg==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.39.1", + "@opentelemetry/sdk-trace-web": "^1.8.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0", + "zone.js": "0.11.4" + } + }, + "node_modules/@opentelemetry/instrumentation-xml-http-request": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-xml-http-request/-/instrumentation-xml-http-request-0.39.1.tgz", + "integrity": "sha512-hj8Va+2uNEYKPwrUwiUwFfFBooI62wfnCeqizcneIaz0MC1Nqh86C40amivTfzKcvmSeEmwDYfXJ6vTSKvq07g==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/instrumentation": "0.39.1", + "@opentelemetry/sdk-trace-web": "1.13.0", + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.39.1.tgz", + "integrity": "sha512-Pv5X8fbi6jD/RJBePyn7MnCSuE6MbPB6dl+7YYBWJ5RcMGYMwvLXjd4h2jWsPV2TSUg38H/RoSP0aXvQ06Y7iw==", + "dependencies": { + "@opentelemetry/core": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.39.1.tgz", + "integrity": "sha512-0hgVnXXz5efI382B/24NxD4b6Zxlh7nxCdJkxkdmQMbn0yRiwoq/ZT+QG8eUL6JNzsBAV1WJlF5aJNsL8skHvw==", + "dependencies": { + "@opentelemetry/api-logs": "0.39.1", + "@opentelemetry/core": "1.13.0", + "@opentelemetry/resources": "1.13.0", + "@opentelemetry/sdk-logs": "0.39.1", + "@opentelemetry/sdk-metrics": "1.13.0", + "@opentelemetry/sdk-trace-base": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.5.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.13.0.tgz", + "integrity": "sha512-euqjOkiN6xhjE//0vQYGvbStxoD/WWQRhDiO0OTLlnLBO9Yw2Gd/VoSx2H+svsebjzYk5OxLuREBmcdw6rbUNg==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.5.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.39.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.39.1.tgz", + "integrity": "sha512-/gmgKfZ1ZVFporKuwsewqIyvaUIGpv76JZ7lBpHQQPb37IMpaXO6pdqFI4ebHAWfNIm3akMyhmdtzivcgF3lgw==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/resources": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.5.0", + "@opentelemetry/api-logs": ">=0.38.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.13.0.tgz", + "integrity": "sha512-MOjZX6AnSOqLliCcZUrb+DQKjAWXBiGeICGbHAGe5w0BB18PJIeIo995lO5JSaFfHpmUMgJButTPfJJD27W3Vg==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/resources": "1.13.0", + "lodash.merge": "4.6.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.5.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.13.0.tgz", + "integrity": "sha512-moTiQtc0uPR1hQLt6gLDJH9IIkeBhgRb71OKjNHZPE1VF45fHtD6nBDi5J/DkTHTwYP5X3kBJLa3xN7ub6J4eg==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/resources": "1.13.0", + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.5.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-web": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-web/-/sdk-trace-web-1.13.0.tgz", + "integrity": "sha512-8iYENSMKKfKSZ9fEcTMkc6H0hs7bmnx14GeIT19r7eN0HqXli93WJP6eVQC/Exkz03D4uEKAdjqxKJzXCewKYg==", + "dependencies": { + "@opentelemetry/core": "1.13.0", + "@opentelemetry/sdk-trace-base": "1.13.0", + "@opentelemetry/semantic-conventions": "1.13.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.5.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.13.0.tgz", + "integrity": "sha512-LMGqfSZkaMQXqewO0o1wvWr/2fQdCh4a3Sqlxka/UsJCe0cfLulh6x2aqnKLnsrSGiCq5rSCwvINd152i0nCqw==", + "engines": { + "node": ">=14" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/htmx.org": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.2.tgz", + "integrity": "sha512-ZGbucKcalQyXdGUl+4Zt3xdRDPmNy70yNhMyDG1eDYUm/ImxmSo2rhIBDa53XitrAVhA+/CGgry+wJ1SO77wrA==" + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/require-in-the-middle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.1.0.tgz", + "integrity": "sha512-6f86Mh0vWCxqKKatRPwgY6VzYmcVay3WUTIpJ1ILBCNh+dTWabMR1swKGKz3XcEZ5mgjndzRu7fQ+44G2H9Gew==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tslib": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/zone.js": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.4.tgz", + "integrity": "sha512-DDh2Ab+A/B+9mJyajPjHFPWfYU1H+pdun4wnnk0OcQTNjem1XQSZ2CDW+rfZEUDjv5M19SBqAkjZi0x5wuB5Qw==", + "dependencies": { + "tslib": "^2.0.0" + } + } + } +} diff --git a/examples/roll_dice_elli/package.json b/examples/roll_dice_elli/package.json new file mode 100644 index 0000000..34ef09e --- /dev/null +++ b/examples/roll_dice_elli/package.json @@ -0,0 +1,16 @@ +{ + "dependencies": { + "@opentelemetry/api": "^1.4.1", + "@opentelemetry/auto-instrumentations-web": "^0.32.2", + "@opentelemetry/context-zone": "^1.13.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.39.1", + "@opentelemetry/exporter-zipkin": "^1.13.0", + "@opentelemetry/instrumentation-document-load": "^0.32.2", + "@opentelemetry/sdk-trace-web": "^1.13.0", + "esbuild": "0.17.19", + "htmx.org": "^1.9.2" + }, + "scripts": { + "build": "esbuild js/app.js --bundle --outfile=priv/static/index.js" + } +} diff --git a/examples/roll_dice_elli/priv/static/index_no_meta_tag.html b/examples/roll_dice_elli/priv/static/index_no_meta_tag.html new file mode 100644 index 0000000..7cc62ae --- /dev/null +++ b/examples/roll_dice_elli/priv/static/index_no_meta_tag.html @@ -0,0 +1,13 @@ + + + + + +
0
+ + + + + diff --git a/examples/roll_dice_elli/rebar.config b/examples/roll_dice_elli/rebar.config new file mode 100644 index 0000000..7ac399f --- /dev/null +++ b/examples/roll_dice_elli/rebar.config @@ -0,0 +1,28 @@ +{erl_opts, [debug_info]}. +{deps, [elli, + recon, + opentelemetry_api, + opentelemetry_exporter, + opentelemetry, + opentelemetry_elli, + + {opentelemetry_api_experimental, + {git_subdir, "http://github.com/tsloughter/opentelemetry-erlang", + {branch, "main"}, "apps/opentelemetry_api_experimental"}}, + {opentelemetry_experimental, + {git_subdir, "http://github.com/tsloughter/opentelemetry-erlang", + {branch, "main"}, "apps/opentelemetry_experimental"}} + ]}. + +%% builds js/app.js into priv/static/index.js +{pre_hooks, [{compile, "npm run build"}]}. + +{relx, [{release, {roll_dice, "0.1.0"}, + [opentelemetry_exporter, + opentelemetry_experimental, + opentelemetry, + recon, + roll_dice, + sasl]} +]}. + diff --git a/examples/roll_dice_elli/rebar.lock b/examples/roll_dice_elli/rebar.lock new file mode 100644 index 0000000..d7c570f --- /dev/null +++ b/examples/roll_dice_elli/rebar.lock @@ -0,0 +1,70 @@ +{"1.2.0", +[{<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},2}, + {<<"chatterbox">>,{pkg,<<"ts_chatterbox">>,<<"0.13.0">>},2}, + {<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},2}, + {<<"elli">>,{pkg,<<"elli">>,<<"3.3.0">>},0}, + {<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},2}, + {<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.16.0">>},1}, + {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},3}, + {<<"opentelemetry">>, + {git_subdir,"http://github.com/tsloughter/opentelemetry-erlang", + {ref,"1fc3bc54d9954048014df7fd6227c6b783fd7047"}, + "apps/opentelemetry"}, + 0}, + {<<"opentelemetry_api">>, + {git_subdir,"http://github.com/tsloughter/opentelemetry-erlang", + {ref,"1fc3bc54d9954048014df7fd6227c6b783fd7047"}, + "apps/opentelemetry_api"}, + 0}, + {<<"opentelemetry_api_experimental">>, + {git_subdir,"http://github.com/tsloughter/opentelemetry-erlang", + {ref,"1fc3bc54d9954048014df7fd6227c6b783fd7047"}, + "apps/opentelemetry_api_experimental"}, + 0}, + {<<"opentelemetry_elli">>,{pkg,<<"opentelemetry_elli">>,<<"0.2.0">>},0}, + {<<"opentelemetry_experimental">>, + {git_subdir,"http://github.com/tsloughter/opentelemetry-erlang", + {ref,"1fc3bc54d9954048014df7fd6227c6b783fd7047"}, + "apps/opentelemetry_experimental"}, + 0}, + {<<"opentelemetry_exporter">>, + {pkg,<<"opentelemetry_exporter">>,<<"1.4.1">>}, + 0}, + {<<"opentelemetry_semantic_conventions">>, + {pkg,<<"opentelemetry_semantic_conventions">>,<<"0.2.0">>}, + 1}, + {<<"recon">>,{pkg,<<"recon">>,<<"2.5.3">>},0}, + {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},2}, + {<<"tls_certificate_check">>, + {pkg,<<"tls_certificate_check">>,<<"1.18.0">>}, + 1}]}. +[ +{pkg_hash,[ + {<<"acceptor_pool">>, <<"43C20D2ACAE35F0C2BCD64F9D2BDE267E459F0F3FD23DAB26485BF518C281B21">>}, + {<<"chatterbox">>, <<"6F059D97BCAA758B8EA6FFFE2B3B81362BD06B639D3EA2BB088335511D691EBF">>}, + {<<"ctx">>, <<"8FF88B70E6400C4DF90142E7F130625B82086077A45364A78D208ED3ED53C7FE">>}, + {<<"elli">>, <<"089218762A7FF3D20AE81C8E911BD0F73EE4EE0ED85454226D1FC6B4FFF3B4F6">>}, + {<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>}, + {<<"grpcbox">>, <<"B83F37C62D6EECA347B77F9B1EC7E9F62231690CDFEB3A31BE07CD4002BA9C82">>}, + {<<"hpack">>, <<"17670F83FF984AE6CD74B1C456EDDE906D27FF013740EE4D9EFAA4F1BF999633">>}, + {<<"opentelemetry_elli">>, <<"0FECED66B5D3C4590C249505339FBA8FFE1B3C2CB939B2EABD3574A690CC1F01">>}, + {<<"opentelemetry_exporter">>, <<"5C80C3A22EC084B4E0A9AC7D39A435B332949B2DCEEC9FB19F5C5D2CA8AE1D56">>}, + {<<"opentelemetry_semantic_conventions">>, <<"B67FE459C2938FCAB341CB0951C44860C62347C005ACE1B50F8402576F241435">>}, + {<<"recon">>, <<"739107B9050EA683C30E96DE050BC59248FD27EC147696F79A8797FF9FA17153">>}, + {<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>}, + {<<"tls_certificate_check">>, <<"75699BC855EA18DE358E3024ABD73384691320BB7A0C98AC90A74475311C1AE3">>}]}, +{pkg_hash_ext,[ + {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>}, + {<<"chatterbox">>, <<"B93D19104D86AF0B3F2566C4CBA2A57D2E06D103728246BA1AC6C3C0FF010AA7">>}, + {<<"ctx">>, <<"A14ED2D1B67723DBEBBE423B28D7615EB0BDCBA6FF28F2D1F1B0A7E1D4AA5FC2">>}, + {<<"elli">>, <<"698B13B33D05661DB9FE7EFCBA41B84825A379CCE86E486CF6AFF9285BE0CCF8">>}, + {<<"gproc">>, <<"580ADAFA56463B75263EF5A5DF4C86AF321F68694E7786CB057FD805D1E2A7DE">>}, + {<<"grpcbox">>, <<"294DF743AE20A7E030889F00644001370A4F7CE0121F3BBDAF13CF3169C62913">>}, + {<<"hpack">>, <<"06F580167C4B8B8A6429040DF36CC93BBA6D571FAEAEC1B28816523379CBB23A">>}, + {<<"opentelemetry_elli">>, <<"41A8DBDA4781179357E7C6EF40BEC8E9DB9E7637A63C2AAE8B740F099ADD4392">>}, + {<<"opentelemetry_exporter">>, <<"5A0FF6618B0F7370BD10B50E64099A4C2AA52145AE6567CCCF7D76BA2D32E079">>}, + {<<"opentelemetry_semantic_conventions">>, <<"D61FA1F5639EE8668D74B527E6806E0503EFC55A42DB7B5F39939D84C07D6895">>}, + {<<"recon">>, <<"6C6683F46FD4A1DFD98404B9F78DCABC7FCD8826613A89DCB984727A8C3099D7">>}, + {<<"ssl_verify_fun">>, <<"BDB0D2471F453C88FF3908E7686F86F9BE327D065CC1EC16FA4540197EA04680">>}, + {<<"tls_certificate_check">>, <<"8DE62FF34E59317211567E3B1AE70866DF195895B051193C21ABC381276D395B">>}]} +]. diff --git a/examples/roll_dice_elli/src/roll_dice.app.src b/examples/roll_dice_elli/src/roll_dice.app.src new file mode 100644 index 0000000..e0a6676 --- /dev/null +++ b/examples/roll_dice_elli/src/roll_dice.app.src @@ -0,0 +1,19 @@ +{application, roll_dice, + [{description, "OpenTelemetry example application"}, + {vsn, "0.1.0"}, + {registered, []}, + {mod, {roll_dice_app, []}}, + {applications, + [kernel, + stdlib, + elli, + opentelemetry_api, + opentelemetry_api_experimental, + opentelemetry_elli + ]}, + {env,[]}, + {modules, []}, + + {licenses, ["Apache-2.0"]}, + {links, []} + ]}. diff --git a/examples/roll_dice_elli/src/roll_dice_app.erl b/examples/roll_dice_elli/src/roll_dice_app.erl new file mode 100644 index 0000000..a2ef611 --- /dev/null +++ b/examples/roll_dice_elli/src/roll_dice_app.erl @@ -0,0 +1,26 @@ +%%%------------------------------------------------------------------- +%% @doc roll_dice public API +%% @end +%%%------------------------------------------------------------------- + +-module(roll_dice_app). + +-behaviour(application). + +-export([start/2, stop/1]). + +-include("roll_dice_instruments.hrl"). +-include_lib("opentelemetry_api_experimental/include/otel_meter.hrl"). + +start(_StartType, _StartArgs) -> + create_instruments(), + roll_dice_sup:start_link(). + +stop(_State) -> + ok. + +%% internal functions + +create_instruments() -> + ?create_counter(?ROLL_COUNTER, #{description => <<"The number of rolls by roll value.">>, + unit => '1'}). diff --git a/examples/roll_dice_elli/src/roll_dice_handler.erl b/examples/roll_dice_elli/src/roll_dice_handler.erl new file mode 100644 index 0000000..0753071 --- /dev/null +++ b/examples/roll_dice_elli/src/roll_dice_handler.erl @@ -0,0 +1,59 @@ +-module(roll_dice_handler). + +-export([handle/2, + handle_event/3]). + +-include_lib("elli/include/elli.hrl"). +-behaviour(elli_handler). + +-include("roll_dice_instruments.hrl"). +-include_lib("opentelemetry_api/include/otel_tracer.hrl"). +-include_lib("opentelemetry_api_experimental/include/otel_meter.hrl"). + +handle(Req, _Args) -> + handle(Req#req.method, elli_request:path(Req), Req). + +handle('GET', [<<"rolldice">>], _Req) -> + ?update_name(<<"GET /rolldice">>), + Roll = do_roll(), + {ok, [], erlang:integer_to_binary(Roll)}; +handle('GET', [], _Req) -> + ?update_name(<<"GET /">>), + [{_, TraceParent}] = otel_propagator_text_map:inject([]), + {ok, [], index(TraceParent)}; +handle('GET', File=[<<"static">>, _], _Req) -> + PrivDir = code:priv_dir(roll_dice), + Filename = filename:join([PrivDir | File]), + {ok, [], {file, Filename}}. + +handle_event(_Event, _Data, _Args) -> + ok. + +%% + +-spec do_roll() -> integer(). +do_roll() -> + ?with_span(dice_roll, #{}, + fun(_) -> + Roll = rand:uniform(6), + ?set_attribute('roll.value', Roll), + ?counter_add(?ROLL_COUNTER, 1, #{'roll.value' => Roll}), + Roll + end). + +-spec index(unicode:unicode_binary()) -> iolist(). +index(TraceContext) -> + [<<" + + + >, TraceContext, <<"\" /> + + +
0
+ + + + + ">>]. diff --git a/examples/roll_dice_elli/src/roll_dice_instruments.hrl b/examples/roll_dice_elli/src/roll_dice_instruments.hrl new file mode 100644 index 0000000..85ab0dc --- /dev/null +++ b/examples/roll_dice_elli/src/roll_dice_instruments.hrl @@ -0,0 +1 @@ +-define(ROLL_COUNTER, roll_counter). diff --git a/examples/roll_dice_elli/src/roll_dice_sup.erl b/examples/roll_dice_elli/src/roll_dice_sup.erl new file mode 100644 index 0000000..e5470c0 --- /dev/null +++ b/examples/roll_dice_elli/src/roll_dice_sup.erl @@ -0,0 +1,41 @@ +%%%------------------------------------------------------------------- +%% @doc roll_dice top level supervisor. +%% @end +%%%------------------------------------------------------------------- + +-module(roll_dice_sup). + +-behaviour(supervisor). + +-export([start_link/0]). + +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +init([]) -> + Port = list_to_integer(os:getenv("PORT", "3000")), + + SupFlags = #{strategy => one_for_all, + intensity => 5, + period => 10}, + + ElliOpts = [{callback, elli_middleware}, + {callback_args, [{mods, [{otel_elli_middleware, []}, + {roll_dice_handler, []}]}]}, + {port, Port}], + + + ChildSpecs = [#{id => roll_dice_http, + start => {elli, start_link, [ElliOpts]}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [roll_dice_handler]}], + + {ok, {SupFlags, ChildSpecs}}. + +%% internal functions