Compare commits

...

1819 Commits
v0.4.1 ... main

Author SHA1 Message Date
renovate[bot] bcd7607f01
chore(deps): update github/codeql-action action to v3.29.11 (#890)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-22 11:19:45 -06:00
renovate[bot] 409815f017
chore(deps): update github/codeql-action action to v3.29.10 (#885)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 09:00:21 -06:00
renovate[bot] 9bfd9c6657
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.132.4 (#884)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-18 10:30:30 -06:00
marc0s 73f76ccd53
fix: make experimental honour the OTEL_SDK_DISABLED env var (#876)
* fix: make experimental honour the OTEL_SDK_DISABLED env var

Modify the application so it takes into consideration the truthy value
of `OTEL_SDK_DISABLED` env var and skip starting the supervision tree.

* fix: add missing export for record/5 for otel_meter_noop
2025-08-18 08:59:20 -06:00
renovate[bot] 7fdc5b4004
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.132.2 (#882)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-13 06:18:10 -06:00
renovate[bot] b27dc2f019
chore(deps): update github/codeql-action action to v3.29.9 (#881)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-12 11:38:23 -06:00
renovate[bot] c1be48a790
chore(deps): update actions/checkout action to v5 (#880)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 13:22:00 -06:00
renovate[bot] 95aa0e659c
chore(deps): update actions/checkout action to v4.3.0 (#879)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 06:55:20 -06:00
renovate[bot] e48a97ba42
chore(deps): update dependency python to 3.13 (#878)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-10 06:02:34 -06:00
renovate[bot] 5f3d1cc279
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.131.1 (#871)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-10 05:47:27 -06:00
renovate[bot] d8db1bd9bc
chore(deps): update github/codeql-action action to v3.29.8 (#877)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-10 04:16:41 -06:00
renovate[bot] 37e47aff94
chore(deps): update github/codeql-action action to v3.29.7 (#869)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-08 04:35:34 -06:00
Tristan Sloughter dc6712610c
bump patch version of api, sdk and exporter (#875) 2025-08-07 04:21:58 -06:00
OpenTelemetry Bot 44f7339f45
Sort contributor listings and remove affiliation from emeriti (#872)
Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
2025-07-10 02:48:42 -06:00
OpenTelemetry Bot 189ba95127
Add minimum token permissions for all github workflow files (#870)
Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
2025-07-02 08:08:08 -06:00
Bryan Naegele ba1d543967
Create repository-settings.md (#866)
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2025-07-02 02:59:30 -06:00
OpenTelemetry Bot 973468dcd4
Update community member listings (#867)
* Update community member listings

* Fix outdated community membership link

---------

Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
2025-06-30 13:12:50 -06:00
renovate[bot] 6b68f95c71
chore(deps): update github/codeql-action action to v3.29.0 (#865)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-15 21:26:00 -06:00
Bryan Naegele c3937bcfb5
Fix the inconsistent hex value encoding for log metadata (#851)
* Fix the inconsistent hex value encoding for log metadata

* Format

* Dialyzer error

* Add test
2025-06-15 21:24:19 -06:00
Tristan Sloughter 7faf9312d3
Merge pull request #864 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.128.0
2025-06-10 07:34:08 -06:00
renovate[bot] fdb342ec28
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.128.0 2025-06-09 22:32:08 +00:00
Fred Hebert cc2bebb9b2
Merge pull request #863 from open-telemetry/renovate/github-codeql-action-3.x
chore(deps): update github/codeql-action action to v3.28.19
2025-06-03 14:57:43 -04:00
renovate[bot] 2d0eaa639f
chore(deps): update github/codeql-action action to v3.28.19 2025-06-03 18:30:31 +00:00
Fred Hebert 048df9ad57
Merge pull request #857 from open-telemetry/renovate/fossas-fossa-action-1.x
chore(deps): update fossas/fossa-action action to v1.7.0
2025-06-03 14:29:55 -04:00
renovate[bot] b6fdcabf33 chore(deps): update fossas/fossa-action action to v1.7.0 2025-06-03 14:23:14 -04:00
Fred Hebert 8c4d4dfe1c
Merge pull request #856 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.127.0
2025-06-03 09:16:16 -04:00
renovate[bot] fa95df1967
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.127.0 2025-06-02 20:52:02 +00:00
Fred Hebert f2acce1b4e
Merge pull request #862 from open-telemetry/renovate/ex_doc-0.x-lockfile
chore(deps): update dependency ex_doc to v0.38.2
2025-06-02 16:51:34 -04:00
renovate[bot] 015998c516 chore(deps): update dependency ex_doc to v0.38.2 2025-06-02 16:49:32 -04:00
Fred Hebert 7181ed30ea
Merge pull request #861 from open-telemetry/renovate/ossf-scorecard-action-2.x
chore(deps): update ossf/scorecard-action action to v2.4.2
2025-06-02 16:48:17 -04:00
renovate[bot] 0b05f00ce4 chore(deps): update ossf/scorecard-action action to v2.4.2 2025-06-02 16:45:21 -04:00
Fred Hebert 0961f69b17
Merge pull request #858 from open-telemetry/renovate/github-codeql-action-3.x
chore(deps): update github/codeql-action action to v3.28.18
2025-06-02 16:44:51 -04:00
renovate[bot] 7b179c0a0d
chore(deps): update github/codeql-action action to v3.28.18 2025-06-02 19:51:42 +00:00
Fred Hebert cabdd7c358
Merge pull request #854 from open-telemetry/renovate/ex_doc-0.x
chore(deps): update dependency ex_doc to ~> 0.38
2025-06-02 15:49:59 -04:00
renovate[bot] dc60312cc4
chore(deps): update dependency ex_doc to ~> 0.38 2025-05-09 19:32:25 +00:00
Bryan Naegele 3a1909dc7c
chore(deps): update github/codeql-action action to v3.28.17 (#849)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github/codeql-action](https://redirect.github.com/github/codeql-action) | action | patch | `v3.28.16` -> `v3.28.17` |

---

### Release Notes

<details>
<summary>github/codeql-action (github/codeql-action)</summary>

### [`v3.28.17`](https://redirect.github.com/github/codeql-action/compare/v3.28.16...v3.28.17)

[Compare Source](https://redirect.github.com/github/codeql-action/compare/v3.28.16...v3.28.17)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/open-telemetry/opentelemetry-erlang).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNjQuMCIsInVwZGF0ZWRJblZlciI6IjM5LjI2NC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2025-05-02 12:56:19 -06:00
renovate[bot] 5931182788
chore(deps): update github/codeql-action action to v3.28.17 2025-05-02 10:06:45 +00:00
Fred Hebert 4fc7103045
Merge pull request #848 from open-telemetry/renovate/github-codeql-action-3.x
chore(deps): update github/codeql-action action to v3.28.16
2025-04-23 13:33:54 -04:00
renovate[bot] 5afc5122d5
chore(deps): update github/codeql-action action to v3.28.16 2025-04-23 16:47:11 +00:00
Tristan Sloughter 6acf7fd2c8
Merge pull request #821 from msutkowski/ms/add-spec-links
chore: add relevant links to spec in doc blocks
2025-04-11 11:15:56 -06:00
Tristan Sloughter e8c3458304
Merge branch 'main' into ms/add-spec-links 2025-04-11 11:08:29 -06:00
Fred Hebert d586b0f3a8
Merge pull request #847 from open-telemetry/renovate/github-codeql-action-3.x
chore(deps): update github/codeql-action action to v3.28.15
2025-04-10 15:28:02 -04:00
renovate[bot] 167a45c813
chore(deps): update github/codeql-action action to v3.28.15 2025-04-07 23:25:02 +00:00
Fred Hebert 10df36f01f
Merge pull request #846 from open-telemetry/renovate/github-codeql-action-3.x
chore(deps): update github/codeql-action action to v3.28.14
2025-04-07 10:56:31 -04:00
renovate[bot] bb20252273
chore(deps): update github/codeql-action action to v3.28.14 2025-04-07 13:02:48 +00:00
Fred Hebert bf3af454e9
Merge pull request #845 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.123.0
2025-04-02 08:33:45 -04:00
Fred Hebert 072b5fbcda
Merge branch 'main' into renovate/otel-opentelemetry-collector-contrib-0.x 2025-04-02 08:31:01 -04:00
Fred Hebert 3e61d76305
Merge pull request #844 from open-telemetry/renovate/github-codeql-action-3.x
chore(deps): update github/codeql-action action to v3.28.13
2025-04-02 08:30:27 -04:00
renovate[bot] a239b8f80e
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.123.0 2025-04-01 16:42:37 +00:00
renovate[bot] f178d20355
chore(deps): update github/codeql-action action to v3.28.13 2025-03-31 22:19:13 +00:00
Bryan Naegele b6d65efacf
Merge pull request #843 from opentelemetrybot/ossf-scorecard
Add ossf-scorecard scanning workflow
2025-03-31 16:18:33 -06:00
otelbot 02314c2697 Add ossf-scorecard scanning workflow 2025-03-31 22:29:07 +01:00
Tristan Sloughter 6d073e7c6f
Merge pull request #837 from tsloughter/metric-docs
simplify metrics API and add metrics READMEs
2025-03-27 08:52:58 -06:00
Tristan Sloughter 4a89bc27ab
Merge branch 'main' into metric-docs 2025-03-27 08:31:14 -06:00
Fred Hebert 9a913d02f5
Merge pull request #841 from open-telemetry/renovate/fossas-fossa-action-1.x
chore(deps): update fossas/fossa-action action to v1.6.0
2025-03-23 09:47:07 -04:00
Tristan Sloughter a19618669e
address fred's comments on metric's readmes 2025-03-23 06:16:01 -06:00
Tristan Sloughter cfa856bf13
add register_callback observable instrument macro 2025-03-23 06:07:11 -06:00
Tristan Sloughter 278a599b24
update elixir experimental api for simplified metrics api 2025-03-23 06:07:10 -06:00
Tristan Sloughter 84d46d524a
format api mix.exs 2025-03-23 06:07:10 -06:00
Tristan Sloughter b6685bb408
remove metrics api that accepts an intsrument for just name 2025-03-23 06:07:10 -06:00
Tristan Sloughter 9a65ab1d7a
add some more docs about instruments 2025-03-23 06:07:09 -06:00
Tristan Sloughter a5298f779e
use rebar3 and mix for api docs 2025-03-23 06:07:09 -06:00
Tristan Sloughter 30aa8e2c02
fix propagator text map docs reference to extract/3 to extract/2 2025-03-23 06:07:09 -06:00
Tristan Sloughter ea424e247f
start of docs for metrics api/sdk 2025-03-23 06:07:08 -06:00
renovate[bot] 0aabc5f267
chore(deps): update fossas/fossa-action action to v1.6.0 2025-03-21 03:10:52 +00:00
Fred Hebert a55b62b2fb
Merge pull request #840 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.122.1
2025-03-19 16:50:52 -04:00
renovate[bot] fbe4819a74
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.122.1 2025-03-19 19:40:53 +00:00
Fred Hebert 4e49358b0d
Merge pull request #838 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.121.0
2025-03-10 10:18:43 -04:00
renovate[bot] 6ce7aed666
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.121.0 2025-03-10 14:14:09 +00:00
Fred Hebert 64ad84f57c
Merge pull request #839 from open-telemetry/renovate/ex_doc-0.x-lockfile
chore(deps): update dependency ex_doc to v0.37.3
2025-03-10 10:13:33 -04:00
renovate[bot] 2f27e98aea
chore(deps): update dependency ex_doc to v0.37.3 2025-03-06 15:35:48 +00:00
Tristan Sloughter 20538e61fa
Merge pull request #825 from RichardChukwu/main
Create a Setup Guide
2025-03-02 05:07:39 -07:00
Richard Chukwu a3d117ee89
Update CONTRIBUTING.md 2025-02-26 18:12:32 +01:00
Richard Chukwu bc0c3ad708
Merge branch 'main' into main 2025-02-24 00:09:57 +01:00
Tristan Sloughter 4ced0ae4d9
Merge branch 'main' into ms/add-spec-links 2025-02-22 17:08:35 -07:00
Tristan Sloughter a8efe4c78e
Merge pull request #836 from tsloughter/fix-batch-interval
fix batch export interval to match spec at 5 sec
2025-02-22 16:19:54 -07:00
Tristan Sloughter 40de50142e
fix batch export interval to match spec at 30 seconds 2025-02-22 11:09:48 -07:00
Fred Hebert 5ccb4f6d3e
Merge pull request #835 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.120.0
2025-02-20 10:19:40 -05:00
Richard Chukwu 12bca98eef
Merge branch 'main' into main 2025-02-20 13:30:01 +01:00
renovate[bot] 0050b86f66
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.120.0 2025-02-19 23:12:02 +00:00
Fred Hebert 673361c49e
Merge pull request #834 from open-telemetry/renovate/ex_doc-0.x-lockfile
chore(deps): update dependency ex_doc to v0.37.2
2025-02-19 13:02:03 -05:00
renovate[bot] cb7a06ad92
chore(deps): update dependency ex_doc to v0.37.2 2025-02-19 10:36:23 +00:00
Tristan Sloughter eba036fadc
Merge branch 'main' into main 2025-02-19 03:34:59 -07:00
Tristan Sloughter 7476b83adc
Merge pull request #802 from open-telemetry/ts/bump-exp-0.5.2-0.5.1
bump experimental api and sdk versions (0.5.2 and 0.5.1)
2025-02-19 03:33:47 -07:00
Tristan Sloughter 3a60af780d
remove unneeded eqwalizer-support rebar3 package 2025-02-19 03:29:01 -07:00
Tristan Sloughter 5443ed9d5a
bump experimental api and sdk versions (0.5.2 and 0.6.0) 2025-02-19 03:28:59 -07:00
Bryan Naegele c884b6ffa9
Merge pull request #833 from trask/fossa
Try to fix FOSSA workflow
2025-02-18 17:05:27 -07:00
Trask Stalnaker 898cc95a87 elixir too 2025-02-18 15:08:08 -08:00
Trask Stalnaker 6342d609c9 Try to fix FOSSA workflow 2025-02-18 14:44:05 -08:00
Richard Chukwu 1eb5d0c20e
Update CONTRIBUTING.md
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2025-02-18 14:23:38 +01:00
Richard Chukwu c0fe90c763
Update CONTRIBUTING.md 2025-02-18 11:58:51 +01:00
Richard Chukwu 595dd1c56f
Merge branch 'main' into main 2025-02-18 11:35:37 +01:00
Bryan Naegele 0af311479b
Merge pull request #831 from opentelemetrybot/fossa
Add FOSSA scanning workflow
2025-02-17 20:57:07 -07:00
otelbot 56fd62e9df Add FOSSA scanning workflow 2025-02-17 19:47:47 -08:00
Richard Chukwu e5e9933955
Update CONTRIBUTING.md 2025-02-17 21:17:18 +01:00
Richard Chukwu 306d80e08e
Update CONTRIBUTING.md 2025-02-17 16:31:42 +01:00
Richard Chukwu aced78217a
Merge branch 'main' into main 2025-02-14 11:43:28 +01:00
Tristan Sloughter 725c79a33e
Merge pull request #816 from tsloughter/rm-semconv-docs
remove semconv from docs.sh
2025-02-13 06:40:39 -07:00
Tristan Sloughter eceb96678d
Merge branch 'main' into rm-semconv-docs 2025-02-13 06:28:28 -07:00
Fred Hebert a6ff4fcef6
Merge pull request #828 from open-telemetry/renovate/ex_doc-0.x-lockfile
chore(deps): update dependency ex_doc to v0.37.1
2025-02-12 09:16:30 -05:00
renovate[bot] b5564a69cf
chore(deps): update dependency ex_doc to v0.37.1 2025-02-11 11:47:46 +00:00
Fred Hebert 4a3c6ac59e
Merge pull request #827 from open-telemetry/renovate/ex_doc-0.x
chore(deps): update dependency ex_doc to ~> 0.37
2025-02-05 09:34:11 -05:00
renovate[bot] 360898b8cd
chore(deps): update dependency ex_doc to ~> 0.37 2025-02-05 09:22:26 +00:00
Richard Chukwu 77fd0fd4a7
Merge branch 'main' into main 2025-02-05 10:20:28 +01:00
Fred Hebert 9eba140044
Merge pull request #826 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.119.0
2025-02-04 13:45:07 -05:00
renovate[bot] 235c034037
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.119.0 2025-02-04 18:37:08 +00:00
Matt Sutkowski db3920ebaa
Merge branch 'main' into ms/add-spec-links 2025-01-30 12:16:44 -08:00
Richard Chukwu ab99cb4505
Update CONTRIBUTING.md 2025-01-25 22:15:34 +01:00
Richard Chukwu e9f7a2faa1
Update CONTRIBUTING.md 2025-01-25 22:13:58 +01:00
Richard Chukwu 2354bf3f9a
Update CONTRIBUTING.md
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2025-01-25 22:09:37 +01:00
Richard Chukwu 536b58c23c
Update CONTRIBUTING.md
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2025-01-25 22:04:21 +01:00
Richard Chukwu a248429b0a
Create CONTRIBUTING.md 2025-01-24 23:09:19 +01:00
Fred Hebert cc11e124a7
Merge pull request #822 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.118.0
2025-01-22 13:16:35 -05:00
renovate[bot] c693d87042
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.118.0 2025-01-22 01:13:33 +00:00
Matt Sutkowski 91d8e8e3e8 chore: add relevant links to spec in doc blocks 2025-01-20 11:04:01 -08:00
Fred Hebert 1a8bb51daf
Merge pull request #819 from open-telemetry/renovate/dialyxir-1.x-lockfile
chore(deps): update dependency dialyxir to v1.4.5
2025-01-15 15:50:21 -05:00
renovate[bot] 88dbda8afb
chore(deps): update dependency dialyxir to v1.4.5 2025-01-15 20:34:06 +00:00
Fred Hebert e04288e0d6
Merge pull request #818 from open-telemetry/renovate/covertool-2.x-lockfile
chore(deps): update dependency covertool to v2.0.7
2025-01-15 15:32:25 -05:00
renovate[bot] d8dc9dccc9
chore(deps): update dependency covertool to v2.0.7 2025-01-14 22:16:19 +00:00
Fred Hebert 31ebebe9f7
Merge pull request #817 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.117.0
2025-01-13 13:02:42 -05:00
renovate[bot] 65b43c5167
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.117.0 2025-01-08 19:20:51 +00:00
Tristan Sloughter 1bde3c3a92
remove semconv from docs.sh 2025-01-04 11:44:49 -07:00
Bryan Naegele 5ce8adc8d1
Merge pull request #807 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.116.1
2025-01-03 17:24:20 -07:00
renovate[bot] 89141a96e6
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.116.1 2025-01-04 00:22:07 +00:00
Bryan Naegele e1bf9588ea
Merge pull request #809 from josevalim/patch-1
Always install latest ExDoc before generating docs
2025-01-03 17:21:41 -07:00
José Valim 19cff932c1 Always install latest ExDoc before generating docs 2025-01-03 17:18:51 -07:00
Bryan Naegele 8d6e51b04f
Merge pull request #812 from open-telemetry/renovate/ex_doc-0.x
chore(deps): update dependency ex_doc to ~> 0.36
2025-01-03 17:18:23 -07:00
renovate[bot] decb8806f3
chore(deps): update dependency ex_doc to ~> 0.36 2025-01-04 00:16:29 +00:00
Bryan Naegele 98f8454bf9
Merge pull request #815 from bryannaegele/semconv-elixir-vsn
Update min Elixir version in SemConv
2025-01-03 17:15:48 -07:00
Bryan Naegele 391ee279df
Merge branch 'main' into semconv-elixir-vsn 2025-01-03 17:14:01 -07:00
Bryan Naegele 4818920de4
Merge pull request #813 from tsloughter/rm-eq-rebar3
remove unneeded eqwalizer_rebar3 plugin
2025-01-03 17:11:56 -07:00
Tristan Sloughter c04020ea76 bump elp version to release in 12-2024 2025-01-03 17:08:40 -07:00
Tristan Sloughter c4430cbbf4 remove unneeded eqwalizer_rebar3 plugin 2025-01-03 17:08:40 -07:00
Bryan Naegele a8dd29439e
Merge pull request #814 from open-telemetry/drop-otp-24
Update OTP/Elixir versions and drop OTP 23 & 24
2025-01-03 17:07:53 -07:00
Bryan Naegele ae832bfa1f
Merge branch 'main' into semconv-elixir-vsn 2025-01-02 16:27:04 -07:00
Bryan Naegele 1ef301c3c1
Update min Elixir version 2025-01-02 16:24:05 -07:00
Bryan Naegele 07d965a43c
1.14 is not compatible OTP 27 2025-01-02 16:01:53 -07:00
Bryan Naegele 85a53e9931
Update OTP/Elixir versions and drop OTP 23 & 24 2025-01-02 15:54:34 -07:00
Bryan Naegele 9f7affe630
Merge pull request #806 from open-telemetry/ubuntu-latest-deprecation
ubuntu-latest deplrecation
2024-12-02 15:14:37 -07:00
Bryan Naegele e9a943a81b
ubuntu-latest deplrecation 2024-12-02 14:11:52 -07:00
Fred Hebert 0a969d1fd1
Merge pull request #803 from hkrutzer/patch-1
chore: Update Github Action badge URL in README
2024-11-26 09:11:34 -05:00
Hans Krutzer 9e9acfcd5f
chore: Update Github Action badge URL in README 2024-11-25 11:18:50 +01:00
Fred Hebert 4af0e4d0fc
Merge pull request #800 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.114.0
2024-11-21 09:43:18 -05:00
renovate[bot] b5f877c54b
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.114.0 2024-11-21 14:26:42 +00:00
Fred Hebert 6bf3fc374c
Merge pull request #801 from open-telemetry/renovate/ex_doc-0.x
chore(deps): update dependency ex_doc to ~> 0.35
2024-11-20 15:23:41 -05:00
renovate[bot] 006d5a0103
chore(deps): update dependency ex_doc to ~> 0.35 2024-11-20 19:19:11 +00:00
Fred Hebert e634efc8de
Merge pull request #799 from open-telemetry/renovate/codecov-codecov-action-5.x
chore(deps): update codecov/codecov-action action to v5
2024-11-14 16:19:52 -05:00
renovate[bot] 1e11112799
chore(deps): update codecov/codecov-action action to v5 2024-11-14 19:29:41 +00:00
Fred Hebert 14bf905bef
Merge pull request #797 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.113.0
2024-11-13 09:28:59 -05:00
renovate[bot] f2d0946d30
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.113.0 2024-11-08 21:45:18 +00:00
Fred Hebert a506d08e84
Merge pull request #794 from open-telemetry/renovate/mikepenz-action-junit-report-5.x
chore(deps): update mikepenz/action-junit-report action to v5
2024-11-08 16:44:56 -05:00
renovate[bot] 8618df9773
chore(deps): update mikepenz/action-junit-report action to v5 2024-11-03 13:08:43 +00:00
Tristan Sloughter 0a38bd4765
Merge pull request #789 from tsloughter/fix-traces-protocol-key
fix: key for otlp traces protocol app configuration
2024-10-24 16:34:37 -07:00
Tristan Sloughter 3a8cbe1348
Merge branch 'main' into fix-traces-protocol-key 2024-10-24 06:18:36 -07:00
Fred Hebert 9631d6cc95
Merge pull request #790 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.112.0
2024-10-24 08:09:34 -04:00
renovate[bot] 037cb8368d
Update otel/opentelemetry-collector-contrib Docker tag to v0.112.0 2024-10-23 15:58:22 +00:00
Tristan Sloughter eb494e8387
add regression test for #788 2024-10-21 05:23:36 -06:00
Tristan Sloughter fedf913000
fix: key for otlp traces protocol app configuration 2024-10-21 04:32:16 -06:00
Tristan Sloughter e5c316e097
Merge pull request #787 from open-telemetry/sdk-api-1.4.0
update sdk dep on api
2024-10-07 18:14:20 -07:00
Tristan Sloughter fd3cd3fd14
Merge branch 'main' into sdk-api-1.4.0 2024-10-07 16:38:29 -07:00
Fred Hebert e2e827c034
Merge pull request #785 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.111.0
2024-10-07 09:26:03 -04:00
Tristan Sloughter 7c04138437
update sdk dep on api 2024-10-06 11:55:22 -06:00
renovate[bot] 18a06fc339
Update otel/opentelemetry-collector-contrib Docker tag to v0.111.0 2024-10-06 17:15:30 +00:00
Tristan Sloughter ba180b6522
Merge pull request #786 from tsloughter/minor-bumps
Minor bumps
2024-10-06 10:15:18 -07:00
Tristan Sloughter fee4ce7694
somehow fixes test timeout when run with cover... 2024-10-06 08:53:27 -06:00
Tristan Sloughter 90f047beca
add OTP 27 to tests 2024-10-06 04:20:29 -06:00
Tristan Sloughter 64543957fd
update changelog and bump minor versions 2024-10-05 05:27:19 -06:00
Tristan Sloughter 332119b119
fix for calling older versions of otlp exporter module 2024-10-05 05:27:19 -06:00
Tristan Sloughter 49b538d841
fix names of exporter_traces export/3 variables 2024-10-05 05:27:18 -06:00
Bryan Naegele 9239c297fd
Merge pull request #783 from tsloughter/api-sdk-bumps
version bumps for api and sdk
2024-10-03 13:46:58 -06:00
Tristan Sloughter 4dd6b60e5f
loosen constraint on api version in sdk 2024-10-03 13:42:51 -06:00
Tristan Sloughter 113f1aaf5f
bump sdk to 1.4.1 2024-10-03 13:29:26 -06:00
Tristan Sloughter ce7b5a5a4e
bump api version to 1.3.1 2024-10-03 13:19:05 -06:00
Tristan Sloughter 1487af0fb1
Merge pull request #782 from tsloughter/metrics-skip-empty
metric exporter: nothing to do for an empty list of metrics
2024-10-03 10:12:37 -07:00
Tristan Sloughter b3144532ac
Merge branch 'main' into metrics-skip-empty 2024-10-03 09:39:47 -07:00
Tristan Sloughter 01fadb80fe
metric exporter: nothing to do for an empty list of metrics 2024-10-01 04:53:57 -06:00
Bryan Naegele 4bf0c435ac
Merge pull request #780 from open-telemetry/hardcode-semconv
Hard code semconv 0.2 values
2024-09-30 15:15:11 -06:00
Bryan Naegele 25d755e6f9 Elixir refs 2024-09-30 15:12:22 -06:00
Bryan Naegele bcd1dd81fc Hard code semconv 0.2 values 2024-09-30 15:12:22 -06:00
Fred Hebert 2c4afaeabd
Merge pull request #781 from open-telemetry/renovate/ubuntu-24.x
Update dependency ubuntu to v24
2024-09-27 10:39:00 -04:00
renovate[bot] 192b1b0d0f
Update dependency ubuntu to v24 2024-09-26 19:34:35 +00:00
Bryan Naegele c69940f95b
Merge pull request #779 from open-telemetry/sem-conv-1.27-release
Set sem-conv package name explicitly
2024-09-25 09:14:04 -06:00
Bryan Naegele b9cd49956a Set sem-conv package name explicitly 2024-09-25 09:03:43 -06:00
Fred Hebert f971df1856
Merge pull request #778 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.110.0
2024-09-24 19:01:11 -04:00
renovate[bot] da60e75150
Update otel/opentelemetry-collector-contrib Docker tag to v0.110.0 2024-09-24 15:34:54 +00:00
Bryan Naegele 8e062c56b2
Merge pull request #777 from open-telemetry/bryannaegele-patch-1
Delete apps/opentelemetry_semantic_conventions/.tool-versions
2024-09-23 16:09:22 -06:00
Bryan Naegele 78e87295fd
Delete apps/opentelemetry_semantic_conventions/.tool-versions 2024-09-23 14:55:59 -06:00
Bryan Naegele fa47500ef4
Merge pull request #733 from open-telemetry/sem-con-1.25
Sem con 1.27.0
2024-09-23 14:12:20 -06:00
Bryan Naegele 056e1563cd
Merge branch 'main' into sem-con-1.25 2024-09-23 14:10:24 -06:00
Tristan Sloughter 0325c1927a
Merge pull request #774 from hoyon/patch-1
Fix invalid warning log causing FORMATTER CRASH
2024-09-23 10:43:46 -07:00
Ho-Yon Mak bda6844589
Fix invalid log format 2024-09-23 17:04:23 +01:00
Bryan Naegele 61ecf5da61
Merge pull request #772 from zhihuizhang17/zhihuizhang/fix-warning
Fix warning by replacing charlist with string
2024-09-16 13:34:18 -06:00
Bryan Naegele 69b41af3c0
Remove non-lang excludes and clean up doc guides 2024-09-16 10:43:34 -06:00
Zhihui Zhang f80cd089d7 fix warning 2024-09-14 15:54:17 +08:00
Bryan Naegele 357178d410
Merge branch 'main' into sem-con-1.25 2024-09-13 20:41:06 -06:00
Bryan Naegele a38fba2d36
Update versioning 2024-09-13 20:36:11 -06:00
Bryan Naegele 3a2dd82e84
Remove more unrelated namespaces 2024-09-13 20:16:30 -06:00
Bryan Naegele cbe3e416c9
v1.27.0 start 2024-09-13 18:40:04 -06:00
Bryan Naegele 053e73187f
Merge pull request #765 from codeboten/patch-1
update collector example with debug exporter
2024-09-11 13:54:10 -06:00
Alex Boten 3aab0a7c74 Update config/otel-collector-config.yaml 2024-09-11 13:51:46 -06:00
Alex Boten 3662004437 update collector example with debug exporter
The logging exporter was renamed debug in 2023, the logging exporter will be removed in the near future, updating the example accordingly.
2024-09-11 13:51:46 -06:00
Fred Hebert 12075ed2f4
Merge pull request #767 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.109.0
2024-09-11 14:16:33 -04:00
renovate[bot] 3236677748
Update otel/opentelemetry-collector-contrib Docker tag to v0.109.0 2024-09-10 22:06:32 +00:00
Bryan Naegele 9042483865
Merge pull request #766 from open-telemetry/elixir-exception-atom
Exception should be atom
2024-09-09 10:16:31 -06:00
Bryan Naegele 1d9c4e597b
Update otel_tests.exs 2024-09-05 19:33:55 -06:00
Bryan Naegele 853696a085
Exception should be atom 2024-09-05 19:29:47 -06:00
Tristan Sloughter 18f0d7f862
Merge pull request #764 from open-telemetry/api-1.3.1
bump api to 1.3.1
2024-09-04 03:05:39 -07:00
Tristan Sloughter 519ad07cba
bump api to 1.3.1 2024-09-03 09:53:29 -06:00
Fred Hebert f039fc3b2f
Merge pull request #762 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.108.0
2024-08-28 09:31:07 -04:00
renovate[bot] 75e00f10ec
Update otel/opentelemetry-collector-contrib Docker tag to v0.108.0 2024-08-27 22:50:55 +00:00
Fred Hebert b732150018
Merge pull request #761 from txssu/main
Fix readme formatting
2024-08-27 10:13:23 -04:00
txssu 007fb63c08 Fix readme formatting 2024-08-27 18:39:28 +05:00
Fred Hebert 7b5417109b
Merge pull request #759 from RichMorin/patch-1
Update README.md
2024-08-20 14:52:17 -04:00
Fred Hebert 9e2c5ec2cd
Merge branch 'main' into patch-1 2024-08-20 14:50:07 -04:00
Fred Hebert 96c1f0d35b
Merge pull request #757 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.107.0
2024-08-20 14:48:04 -04:00
renovate[bot] 0c507b3550
Update otel/opentelemetry-collector-contrib Docker tag to v0.107.0 2024-08-20 01:07:54 +00:00
Bryan Naegele 7da19122d2
Merge pull request #760 from open-telemetry/bryannaegele-patch-1
deprecated compose cmd
2024-08-19 19:07:23 -06:00
Bryan Naegele 2db51949a4
deprecated compose cmd 2024-08-19 11:11:37 -06:00
Bryan Naegele 2fa006d3e2
deprecated compose cmd 2024-08-17 11:37:45 -06:00
Bryan Naegele f377d87be8
Remove unnecessary erl macro def quotes 2024-08-17 11:31:25 -06:00
Bryan Naegele f3e9c52fae
include has to be include_lib for pkgs to compile correctly 2024-08-13 20:38:17 -06:00
Rich Morin 3a659fd213
Update README.md
tidy up the grammar, etc.
2024-08-12 11:52:21 -07:00
Bryan Naegele 8bd1a45883
defdelegate stable elixir enum values 2024-07-30 15:49:33 -06:00
Bryan Naegele e3d0e464b1
Include stable attrs in incubating 2024-07-29 13:44:44 -06:00
Bryan Naegele 841992ef5c
Expand clean targets in makefile 2024-07-26 17:26:01 -06:00
Bryan Naegele f426cb92f8
Update attribute location references 2024-07-26 17:24:35 -06:00
Bryan Naegele 2ea65d018c
Reorganize file layout 2024-07-26 17:18:36 -06:00
Bryan Naegele 9eddc386de
Add schema urls 2024-07-26 17:14:30 -06:00
Bryan Naegele df38bfa07a
Erl enum values to all snake case; fix-up erl atom declarations 2024-07-26 09:30:57 -06:00
Bryan Naegele 66534048ba
Test typo 2024-07-25 21:40:54 -06:00
Bryan Naegele d88ef0aaef
Fix-up file names 2024-07-25 21:31:56 -06:00
Bryan Naegele 9943a0696a
Switch to release binary and makefile 2024-07-25 20:24:14 -06:00
Bryan Naegele aeea23bb19
Fix elixir metrics tmpl 2024-07-25 20:23:40 -06:00
Bryan Naegele b7c8f17e1a
Set up attr filtering for name collision 2024-07-25 16:11:12 -06:00
Bryan Naegele b7decf43e2
Use built-in acronym func and remove name smooshing 2024-07-25 16:10:11 -06:00
Bryan Naegele 2c91bfeb84
Add renamed files 2024-07-25 14:11:31 -06:00
Bryan Naegele 8749795b6a
Run filenames through attributes filters 2024-07-25 12:01:50 -06:00
Bryan Naegele 8504d1629c
Remove custom enum functions 2024-07-25 11:06:10 -06:00
Bryan Naegele 53fe0d3c60
Erlang enum value doc typos 2024-07-24 20:13:27 -06:00
Bryan Naegele 36c4e4f09b
typo 2024-07-24 20:06:47 -06:00
Bryan Naegele 11294fe25d
Adjust enum approach 2024-07-24 20:01:22 -06:00
Bryan Naegele bbcb147474
Align with python 2024-07-23 16:00:35 -06:00
Bryan Naegele 0f3ad395bd
Improve usability of stability opt in lookup 2024-07-23 10:43:27 -06:00
Bryan Naegele 548da527e4
Add semconv stability opt-in fun 2024-07-22 20:51:10 -06:00
Bryan Naegele f3494631cc
Remove java references 2024-07-19 14:43:37 -06:00
Bryan Naegele b2e1a618dc
Clarify version references 2024-07-16 15:19:19 -06:00
Bryan Naegele f50940ccd1
Metrics docs and doc organization refinement 2024-07-16 15:14:59 -06:00
Bryan Naegele 3ec356ed25
Fix elixir metric acronym module names 2024-07-15 18:03:03 -06:00
Bryan Naegele 3429bcf1e6
Add metrics and license to hrl 2024-07-15 17:52:19 -06:00
Bryan Naegele 8005eb01bc
Remove elixir exclude 2024-07-10 17:10:41 -06:00
Bryan Naegele 31018c6ec0
Deps get 2024-07-10 17:08:11 -06:00
Bryan Naegele 0db2398499
Merge branch 'main' into sem-con-1.25 2024-07-10 17:01:52 -06:00
Bryan Naegele e1cf5fd5c7
Nest folder 2024-07-10 16:59:46 -06:00
Bryan Naegele b355a7923b
Move old modules back to old folder 2024-07-10 16:58:49 -06:00
Bryan Naegele 6e19a4a4e8
Undefined 2024-07-10 16:49:00 -06:00
Bryan Naegele dba84aa616
Fixup workflow events 2024-07-10 16:36:29 -06:00
Bryan Naegele 8e52910f98
Fix enum macros and add testing/ci 2024-07-10 16:31:52 -06:00
Bryan Naegele 938ea42bdb
Remove single attribute tmpl 2024-07-10 12:29:06 -06:00
Bryan Naegele 45102546d2
Merge pull request #737 from tsloughter/attribute-iolist
fix support for attribute lists of strings to not flatten them
2024-07-10 08:06:25 -06:00
Bryan Naegele 186535ffe9
Separate incubating attributes 2024-07-09 22:13:47 -06:00
Tristan Sloughter d1e392b75f
keep link record passed in a list of links to a span as is 2024-07-05 04:07:29 -06:00
Tristan Sloughter d2c27f2812
fix support for attribute lists of strings to not flatten them
No longer are attribute values that are lists of strings converted
to a single string. This means Erlang charlists will be sent in
OTLP as a list of integers and iolists as a list of strings. The
user must use characters_to_binary to convert to a binary string
if they wish to set the value to a string when they have a value
of those types now.
2024-07-05 04:07:28 -06:00
Fred Hebert c81e99da3f
Merge pull request #754 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.104.0
2024-07-02 15:53:44 -04:00
renovate[bot] b05b6f1d4f
Update otel/opentelemetry-collector-contrib Docker tag to v0.104.0 2024-07-02 05:20:27 +00:00
Bryan Naegele b921da48e8
enum rework 2024-06-24 18:19:50 -06:00
Bryan Naegele d5677cb72b
Merge pull request #752 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.103.1
2024-06-24 11:26:13 -06:00
renovate[bot] 7cc21dbe18
Update otel/opentelemetry-collector-contrib Docker tag to v0.103.1 2024-06-24 16:24:48 +00:00
Bryan Naegele 82b1319c8f
template typos 2024-06-23 20:26:34 -06:00
Bryan Naegele 3edffcf506
typo 2024-06-23 18:47:40 -06:00
Bryan Naegele 212199c2b9
Remove old tests 2024-06-23 18:43:59 -06:00
Bryan Naegele 2f018604ba
ignore copied guides 2024-06-23 18:43:47 -06:00
Bryan Naegele d5135648e7
Fixup generate script 2024-06-23 18:25:16 -06:00
Bryan Naegele 53eac185cd
1.26.0 and weaver 2024-06-23 18:20:37 -06:00
Bryan Naegele a80626c24e
Pre-enum rework with weaver 2024-06-23 16:32:00 -06:00
Fred Hebert 85de59e536
Merge pull request #750 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.102.1
2024-06-06 18:58:59 -04:00
renovate[bot] 104ec761bf
Update otel/opentelemetry-collector-contrib Docker tag to v0.102.1 2024-06-05 20:11:55 +00:00
Fred Hebert 3b4cde79fd
Merge pull request #749 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.102.0
2024-06-04 14:16:20 -04:00
renovate[bot] 0ee23107ec
Update otel/opentelemetry-collector-contrib Docker tag to v0.102.0 2024-06-04 13:40:04 +00:00
Fred Hebert ea34738803
Merge pull request #748 from open-telemetry/renovate/ex_doc-0.x
Update dependency ex_doc to ~> 0.34
2024-06-01 09:32:01 -04:00
renovate[bot] af37f1113f
Update dependency ex_doc to ~> 0.34 2024-06-01 13:30:02 +00:00
Fred Hebert 86f52d46e8
Merge pull request #745 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.101.0
2024-06-01 09:29:11 -04:00
renovate[bot] 50a5dbae86
Update otel/opentelemetry-collector-contrib Docker tag to v0.101.0 2024-05-24 15:17:53 +00:00
Fred Hebert e6c5c756d9
Merge pull request #743 from open-telemetry/renovate/ex_doc-0.x
Update dependency ex_doc to ~> 0.33
2024-05-24 11:17:30 -04:00
renovate[bot] 0e5082bd1d
Update dependency ex_doc to ~> 0.33 2024-05-21 16:50:08 +00:00
Fred Hebert 7c03aa08c1
Merge pull request #738 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.100.0
2024-05-13 14:42:33 -04:00
renovate[bot] fb3e38ef7a
Update otel/opentelemetry-collector-contrib Docker tag to v0.100.0 2024-05-13 15:05:41 +00:00
Fred Hebert e76abc9aca
Merge pull request #740 from kianmeng/resolve_unused_variable_warning
Resolve unused variable
2024-05-13 11:05:18 -04:00
Fred Hebert 275ebaf682
Merge branch 'main' into resolve_unused_variable_warning 2024-05-13 10:10:38 -04:00
Fred Hebert 51bbad56e1
Merge pull request #739 from kianmeng/fix-typos-again
Fix typos again
2024-05-13 10:09:45 -04:00
Kian-Meng Ang 05a444af7e Resolve unused variable
This resolves the compilation warning:
src/otel_aggregation_sum.erl:119:9: Warning: variable 'N' is unused
2024-05-13 15:46:14 +08:00
Kian-Meng Ang a172d2454f Fix typos again
Found via `typos --format brief`
2024-05-13 15:22:45 +08:00
Tristan Sloughter afb1e8b86d
Merge pull request #726 from whatyouhide/al/otel-propagator-doc
Add docs for all `otel_propagator*` modules
2024-05-02 02:59:46 -06:00
Tristan Sloughter 2253bd56c3
Merge branch 'main' into al/otel-propagator-doc 2024-05-02 02:50:19 -06:00
Bryan Naegele 11177ef06b
Update README.md 2024-04-25 10:04:23 -06:00
Tristan Sloughter a5f4b7b24e
Merge pull request #729 from whatyouhide/al/document-samplers
Document sampler modules
2024-04-24 11:14:34 -06:00
Andrea Leopardi 565a24ff57
Merge branch 'main' into al/document-samplers 2024-04-24 15:09:19 +02:00
Fred Hebert 8512748496
Merge pull request #734 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.99.0
2024-04-23 09:41:03 -04:00
renovate[bot] 062d5753cf
Update otel/opentelemetry-collector-contrib Docker tag to v0.99.0 2024-04-23 04:48:26 +00:00
Andrea Leopardi 9bb72f6064
Merge branch 'main' into al/document-samplers 2024-04-21 10:11:18 +02:00
Bryan Naegele 1bd8c7b2fa
Format generate 2024-04-20 22:07:17 -06:00
Bryan Naegele 8f86370458
Switch to elixir script 2024-04-20 22:00:05 -06:00
Bryan Naegele 3d66e8fd40
Refinement 2024-04-20 21:58:03 -06:00
Bryan Naegele 3ead588f62
Multiple files 2024-04-20 20:30:01 -06:00
Bryan Naegele 3af0ab1f08
single file 2024-04-20 16:33:58 -06:00
Tristan Sloughter ca61a11ba7
Merge pull request #732 from whatyouhide/al/opentelemetry-docs
Document more functions in the "opentelemetry" module
2024-04-20 04:29:04 -06:00
Tristan Sloughter 2046e14b2d
Merge branch 'main' into al/opentelemetry-docs 2024-04-20 04:23:53 -06:00
Tristan Sloughter 2e00cac520
Merge pull request #720 from tsloughter/append-v1-metrics
move metrics and logs to separate exporter modules from traces
2024-04-20 04:15:44 -06:00
Tristan Sloughter ec0bb47ef8
Merge branch 'main' into append-v1-metrics 2024-04-20 04:10:15 -06:00
Andrea Leopardi 98ce452c82
Document more functions in the "opentelemetry" module 2024-04-19 09:03:41 +02:00
Tristan Sloughter 8bd4cb80d0
convert map of attributes to binary
bug in Erlang ETS allowed attributes as maps in select_replace
to appear to work when in fact they will match like a normal `=`
in Erlang, so any metric will be match by another with a subset
of its attributes. Converting to a binary means the attributes
must be exactly equal.
2024-04-18 03:30:48 -06:00
Andrea Leopardi e30700c205
FIXUP 2024-04-18 10:29:20 +02:00
Andrea Leopardi e5ef817116 Fixes 2024-04-16 08:42:55 +02:00
Andrea Leopardi 4bc737a1f4 Document sampler modules 2024-04-16 08:42:55 +02:00
Fred Hebert e7df425b45
Merge pull request #730 from open-telemetry/renovate/ex_doc-0.x
Update dependency ex_doc to ~> 0.32
2024-04-15 09:36:58 -04:00
Andrea Leopardi d53c7cac94
Merge branch 'main' into al/otel-propagator-doc 2024-04-14 16:37:42 +02:00
renovate[bot] 19cf32e9de
Update dependency ex_doc to ~> 0.32 2024-04-14 12:01:05 +00:00
Tristan Sloughter c5ca033335
Merge pull request #727 from whatyouhide/al/resource-docs
Documentation for `otel_resource*` modules
2024-04-14 06:00:11 -06:00
Tristan Sloughter 62553dd09c
Merge branch 'main' into al/resource-docs 2024-04-14 05:20:12 -06:00
Andrea Leopardi 0b055ca30e FIXUP 2024-04-14 13:17:51 +02:00
Andrea Leopardi 17e1843c03
Update apps/opentelemetry/src/otel_resource_detector.erl
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2024-04-14 12:48:05 +02:00
Andrea Leopardi f1256b1d27
Update apps/opentelemetry/src/otel_resource.erl
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2024-04-14 12:47:56 +02:00
Tristan Sloughter f587610ad3
Merge pull request #728 from whatyouhide/al/otel-docs
Group and hide modules in "opentelemetry" app
2024-04-13 02:49:01 -06:00
Andrea Leopardi 5132d62ee6
Merge branch 'main' into al/otel-docs 2024-04-13 10:01:52 +02:00
Fred Hebert cf12a3ce07
Merge pull request #731 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.98.0
2024-04-11 13:12:39 -04:00
renovate[bot] 04f6c8f832
Update otel/opentelemetry-collector-contrib Docker tag to v0.98.0 2024-04-11 06:26:27 +00:00
Tristan Sloughter e1daf9134b
make force_flush sync so tests are not timing dependent 2024-04-08 15:30:05 -06:00
Andrea Leopardi a36d8ec2af
Group and hide modules in "opentelemetry" app 2024-04-07 16:23:45 +03:00
Andrea Leopardi 45bf9ea1c2
FIXUP 2024-04-07 16:13:13 +03:00
Andrea Leopardi f3d0e14174
Fix docs 2024-04-07 16:07:56 +03:00
Andrea Leopardi a64e17b566
Update apps/opentelemetry/src/otel_resource_detector.erl
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2024-04-07 16:06:41 +03:00
Tristan Sloughter 691db48628
logs: skip exporting if batch is empty 2024-04-07 07:05:07 -06:00
Tristan Sloughter beb78d378e
fix logs encoding that requires a Config arguments 2024-04-07 03:05:14 -06:00
Tristan Sloughter dc58c4092e
fix name of metric exporter init module in reader 2024-04-06 15:45:48 -06:00
Tristan Sloughter d7246f2b43
fix metric exporters referencing the correct behaviour they implement 2024-04-06 15:33:52 -06:00
Tristan Sloughter 84850f1254
move common otlp functionality to shared module 2024-04-06 04:32:37 -06:00
Tristan Sloughter a5d2198489
move metrics and logs to separate exporter modules from traces 2024-04-06 04:32:37 -06:00
Andrea Leopardi bb2e6168d4 Document for otel_resource* modules 2024-04-04 20:58:15 +02:00
Andrea Leopardi 2d4276e7ee
Add docs for all otel_propagator* modules 2024-04-03 14:19:52 +02:00
Fred Hebert 8c9dc00196
Merge pull request #718 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.97.0
2024-04-03 08:05:59 -04:00
renovate[bot] 70e024e7a9
Update otel/opentelemetry-collector-contrib Docker tag to v0.97.0 2024-04-03 11:34:25 +00:00
Fred Hebert 6b9a18cb64
Merge pull request #723 from whatyouhide/otel-utils-private
Make the otel_utils module private
2024-04-03 07:34:01 -04:00
Tristan Sloughter 3fa8ad816b
Merge branch 'main' into otel-utils-private 2024-04-03 04:23:56 -06:00
Tristan Sloughter 15fafa12ef
Merge pull request #717 from travelping/fix/708
add otel_span:start_config typespec and use it in the SDK
2024-04-03 02:44:43 -06:00
Andreas Schultz fa4347636b add otel_span:start_config typespec and use it in the SDK
fixes #708

In the API functions, all members of start_opts() are optional.

Before passing the options on the SDK all options are set to sensible
defaults. That makes is possible to have a dedicated start_config()
type where all values are mandatory and optimize the usage of the
settings slightly.
2024-04-02 15:49:39 +02:00
Fred Hebert 77048256df
Merge pull request #709 from travelping/fix/console-exporter
make the console metric exporter handle all values
2024-04-02 09:27:48 -04:00
Andreas Schultz d8f51951cd make the console metric exporter handle all values
The OTLP exporter handles all types of keys, but the debug exporter is
a bit too simplistic and will choke on atoms as attribute keys.

Convert all values to something sensible for printing on the console.
2024-04-02 14:43:57 +02:00
Tristan Sloughter c94c3d3fe5
Merge pull request #722 from whatyouhide/groups-for-modules
Group modules in the docs for opentelemetry_api
2024-04-02 04:48:17 -06:00
Andrea Leopardi cfd0fe5838
Make the otel_utils module private 2024-04-01 21:52:07 +02:00
Andrea Leopardi 7eaec31041
Group modules in the docs for opentelemetry_api 2024-04-01 21:47:48 +02:00
Tristan Sloughter 6f1d63673c
Merge pull request #715 from tsloughter/rm-unused-exporter
removed old unused otel_metric_exporter module
2024-03-21 08:18:23 -06:00
Tristan Sloughter 799860e317
removed old unused otel_metric_exporter module 2024-03-21 03:09:01 -06:00
Tristan Sloughter 3fc90ef450
Merge pull request #714 from tsloughter/exp-docs-configs
add docs configs for experimental apps
2024-03-19 07:56:24 -06:00
Tristan Sloughter 8f01a9a0c2
add docs configs for experimental apps 2024-03-18 12:27:00 -06:00
Tristan Sloughter e8c2b2a7fa
Merge pull request #713 from tsloughter/fix-default-temporality
use correct default temporality for streams based on the instrument kind
2024-03-18 11:27:51 -06:00
Tristan Sloughter aaece44cdb
bump versions of experimental for fix to default temporality 2024-03-18 08:17:31 -06:00
Tristan Sloughter 48d3981919
support empty list boundaries param to get a single bucket histogram 2024-03-18 08:13:38 -06:00
Tristan Sloughter 8fa79e6a8b
use correct default temporality for streams based on the instrument kind 2024-03-18 08:13:33 -06:00
Tristan Sloughter d1f3e35561
Merge pull request #711 from tsloughter/version-bumps
bump version on api, sdk, experimental api, sdk and exporter
2024-03-18 07:59:52 -06:00
Tristan Sloughter 233d283ef0
Merge branch 'main' into version-bumps 2024-03-18 07:53:04 -06:00
Tristan Sloughter c2eedcfda8
Merge pull request #712 from tsloughter/elixir-hisogram-cumulative
add test of Elixir cumulative explicit histogram
2024-03-16 15:47:53 -06:00
Tristan Sloughter e42deeae60
mix format 2024-03-16 11:08:22 -06:00
Tristan Sloughter 19c0b2d635
add test of Elixir cumulative explicit histogram 2024-03-16 11:08:21 -06:00
Tristan Sloughter f8abaf330f
update interdependencies on hex packages 2024-03-15 16:41:58 -06:00
Tristan Sloughter 01acad76b3
bump SDK to depend on API 1.3.x 2024-03-15 15:46:13 -06:00
Tristan Sloughter a03276cceb
bump version on api, sdk, experimental api, sdk and exporter 2024-03-15 15:42:56 -06:00
Fred Hebert c1ccdffb11
Merge pull request #669 from travelping/fix/undefined-units
don't export unit fields in metrics when the unit is undefined
2024-03-13 11:31:06 -04:00
Andreas Schultz cb0f9acdbd don't export unit fields in metrics when the unit is undefined
The term `undefined` is used for metrics where not unit is declared. When exporting
such a metric, we should not set the OTLP unit field to the string "undefined" as that
it not a valid unit.
2024-03-11 12:48:14 +01:00
Tristan Sloughter c3db2613bc
Merge pull request #697 from tsloughter/observe-exemplars
Add a fresh context to each observable callback and test observe exemplars
2024-03-09 09:32:02 -07:00
Tristan Sloughter d83598c846
fixup merger with upstream main branch and producers 2024-03-06 08:06:50 -07:00
Tristan Sloughter cd2c121554
Merge branch 'main' into observe-exemplars 2024-03-06 07:03:57 -07:00
Tristan Sloughter 63d338abfa
Merge pull request #701 from tsloughter/metric-producers
Metric producers
2024-03-06 07:01:48 -07:00
Tristan Sloughter 8b647b0110
Merge branch 'main' into metric-producers 2024-03-06 06:59:35 -07:00
Bryan Naegele ea8a137824
Merge pull request #705 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.96.0
2024-03-05 09:33:41 -07:00
renovate[bot] 62f8e33638
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.96.0 2024-03-05 12:37:50 +00:00
Tristan Sloughter 3bc75ddd28
return updated pdict context from with_ctx macro/function 2024-03-05 04:10:33 -07:00
Tristan Sloughter fc9bd8b3a6
add get_readers function to meter_server for test purposes 2024-03-05 04:10:18 -07:00
Tristan Sloughter def7819930
use matchspec guard to match exemplar keys in ets table
because attributes are a map we can't lookup elements by simply
matching. for example, an empty map would match any set of
attributes
2024-03-05 04:07:33 -07:00
Tristan Sloughter 7701274c55
resolve dialyzer warnings 2024-02-29 09:03:04 -07:00
Tristan Sloughter 52358bd339
move more metric ets usage to single module for better typing 2024-02-29 04:24:00 -07:00
Tristan Sloughter 90384bffe1
handle metrics producer init failing 2024-02-28 13:55:41 -07:00
Tristan Sloughter 695d8d9119
move ets usage in meter_server to single module to better type check 2024-02-28 13:55:41 -07:00
Tristan Sloughter 6ab908dcca
Update apps/opentelemetry_experimental/src/otel_meter_server.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2024-02-28 13:39:26 -07:00
Tristan Sloughter 7c18b64329
Update apps/opentelemetry_experimental/src/otel_metric_reader.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2024-02-28 13:32:18 -07:00
Tristan Sloughter 425c6f07a5
simpify record api and eqwalizer fixes 2024-02-28 05:42:13 -07:00
Tristan Sloughter 7c97883240
fix span is_recording spec to accept undefined atom 2024-02-25 04:57:02 -07:00
Tristan Sloughter b8362930e7
metric producers: implement usage in reader and add test 2024-02-25 04:56:45 -07:00
Tristan Sloughter e6eaa0be0a
fix comment on test about metric servers crashing, not readers 2024-02-24 03:53:05 -07:00
Tristan Sloughter 3b40d4e2e0
add metric producer behaviour 2024-02-24 02:59:53 -07:00
Tristan Sloughter 69fd2771ca
add test of exemplars for observables 2024-02-23 04:16:15 -07:00
Tristan Sloughter 895593f20c
run observable callbacks with new pdict context 2024-02-23 04:16:02 -07:00
Tristan Sloughter 38d3becb3a
add with_ctx function for running a fun with a pdict ctx 2024-02-23 04:14:39 -07:00
Tristan Sloughter 140edfd11a
fix attribute filtering when view attribute isn't in attributes 2024-02-23 04:13:57 -07:00
Tristan Sloughter 6f96105804
Merge pull request #692 from tsloughter/exemplars
add exemplar reservoir support
2024-02-21 15:56:12 -07:00
Tristan Sloughter 52ac8d9074
fix missing comma in updown counter macro 2024-02-21 15:03:50 -07:00
Tristan Sloughter 0f99d9727f
cleanup indentation in histgoram_explicit 2024-02-21 15:03:50 -07:00
Tristan Sloughter 2cd93104d7
make Elixir metric macros accept full instrument 2024-02-21 15:03:50 -07:00
Tristan Sloughter 6708f45df4
make metric macros accept atom name or full instrument 2024-02-21 15:03:50 -07:00
Tristan Sloughter 05e63f969c
test for trace_based exemplar filter 2024-02-21 15:03:50 -07:00
Tristan Sloughter aafe4cd541
remove unneeded drop reservoir from exemplars 2024-02-21 15:03:49 -07:00
Tristan Sloughter d0456e56d5
add eqwalizer ignore to proto modules 2024-02-21 15:03:49 -07:00
Tristan Sloughter 20d326f3c2
add exemplar filter support around reservoir 2024-02-21 15:03:49 -07:00
Tristan Sloughter 0b12e3872a
protos: bump gpb version so @generated is added to module 2024-02-21 15:03:49 -07:00
Tristan Sloughter 7b44cd85e9
fix reservoir offer return to match typespec 2024-02-21 15:03:49 -07:00
Tristan Sloughter 2275aed900
bump protos to 1.1.0 2024-02-21 15:03:49 -07:00
Tristan Sloughter 6c2b263836
bump generation of protos to deal with otp-27 0.0 change 2024-02-21 15:03:48 -07:00
Tristan Sloughter d9e0b0b83c
metrics aggregation behaviour: clean up warnings 2024-02-21 15:03:48 -07:00
Tristan Sloughter 2cb2555d25
store exemplar timestamp in native not nanosecond unit 2024-02-21 15:03:48 -07:00
Tristan Sloughter 1b503a0b70
add exemplars to metric export 2024-02-21 15:03:48 -07:00
Tristan Sloughter 98e301fa79
update aggregator collects to include exemplars 2024-02-21 15:03:48 -07:00
Tristan Sloughter 800b80416c
update Elixir Metric api macros to pass context 2024-02-21 15:03:48 -07:00
Tristan Sloughter b3e157a829
add exemplar offer to last_value aggregation 2024-02-21 15:03:47 -07:00
Tristan Sloughter 4a60385ea7
add generation delta fix to changelog 2024-02-21 15:03:47 -07:00
Tristan Sloughter 62d5eedc75
add exemplars to changelog 2024-02-21 15:03:47 -07:00
Tristan Sloughter 3633acef60
add test of explicit histogram exemplars 2024-02-21 15:03:47 -07:00
Tristan Sloughter 87c7870d3e
add explicit histogram exemplar reservoir 2024-02-21 15:03:47 -07:00
Tristan Sloughter dde3f0f69f
update tests to work with new metric api including ctx 2024-02-21 15:03:47 -07:00
Tristan Sloughter 15e5f65ae9
add float sum aggregator exemplar support 2024-02-21 15:03:47 -07:00
Tristan Sloughter 5d3647cfcb
add option to enable exemplars, off by default 2024-02-21 15:03:46 -07:00
Tristan Sloughter d954e6bc0e
add exemplar reservoir support
Only the drop and simple fixed exemplar reservoir are supported by
this PR, so patchstograms do not yet have exemplar support.

This patch also does not have a toggle for if exemplars are to be
taken or not
2024-02-21 15:03:46 -07:00
Bryan Naegele 10775f3998
Merge pull request #696 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.95.0
2024-02-21 11:33:02 -07:00
renovate[bot] 5b13c57b23
Update otel/opentelemetry-collector-contrib Docker tag to v0.95.0 2024-02-21 18:30:32 +00:00
Tristan Sloughter 82c090f2c9
Merge pull request #691 from tsloughter/metric-streams
update variable/record key ViewAggregation to Stream to match specification
2024-02-10 04:33:20 -07:00
Tristan Sloughter b746f08f3a
update variable/record key ViewAggregation to Stream to match spec
When our metric code was first written the spec	had no term for
the result of matching a View and an Instrument. It has since
been named a 'stream' so this patch replaces our term for the
spec term.
2024-02-09 04:00:41 -07:00
Tristan Sloughter 8d22743b9d
just match on +0.0 in an assertMatch to get rid of OTP-27 warning 2024-02-09 04:00:41 -07:00
Tristan Sloughter 15c1f7c0d2
handle OTP-27 changing -0.0 and +0.0 to not be =:= by using == on 0.0 2024-02-09 04:00:41 -07:00
Fred Hebert f6db9a9129
Merge pull request #690 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
Update otel/opentelemetry-collector-contrib Docker tag to v0.94.0
2024-02-08 13:19:15 -05:00
renovate[bot] 868962fa93
Update otel/opentelemetry-collector-contrib Docker tag to v0.94.0 2024-02-08 16:33:35 +00:00
Tristan Sloughter 13e64d50ab
Merge pull request #677 from tsloughter/delta-checkpoint-generation
use a generation integer to lock writes during each reader checkpoint
2024-02-07 13:09:25 -07:00
Tristan Sloughter 1aa78538d0
Merge branch 'main' into delta-checkpoint-generation 2024-02-07 13:03:00 -07:00
Tristan Sloughter 04cd1471b8
Merge pull request #686 from whatyouhide/al/otel-attributes-docs
Add docs to `otel_attributes`
2024-02-07 04:36:07 -07:00
Andrea Leopardi ff3134cd43
Apply suggestions from code review
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2024-02-07 12:31:17 +01:00
Andrea Leopardi bf735f77e4
Add docs to otel_attributes 2024-02-06 18:08:18 +01:00
Tristan Sloughter 3287d2241c
Merge pull request #680 from whatyouhide/al/some-otel-span-docs
Add docs to half of the functions in `otel_span`
2024-02-06 04:40:04 -07:00
Tristan Sloughter 906af3406a
Merge branch 'main' into al/some-otel-span-docs 2024-02-06 04:35:14 -07:00
Tristan Sloughter 9d302f6d2a
Merge pull request #681 from whatyouhide/al/docs-baggage-ctx
Add docs to `otel_ctx` and `otel_baggage`
2024-02-06 04:28:04 -07:00
Tristan Sloughter 2d37fbcf97
Merge branch 'main' into al/docs-baggage-ctx 2024-02-06 03:38:06 -07:00
Tristan Sloughter 0ca9af16d2
Merge pull request #676 from whatyouhide/al/get-tracer-docs
Document `opentelemetry:get_tracer/*` functions
2024-02-06 03:36:49 -07:00
Tristan Sloughter 0d357ef884
Merge branch 'main' into al/get-tracer-docs 2024-02-06 03:34:38 -07:00
Tristan Sloughter a53ff15644
Merge pull request #675 from whatyouhide/al/span-docs
Add docs to `*_processor` modules
2024-02-06 03:33:38 -07:00
Tristan Sloughter ce08c3c510
Merge branch 'main' into al/span-docs 2024-02-06 03:29:56 -07:00
Andrea Leopardi bd659d717f Fix @ends 2024-02-05 12:14:35 +01:00
Tristan Sloughter 4dd6c871f8
Merge branch 'main' into al/get-tracer-docs 2024-02-05 03:55:40 -07:00
Andrea Leopardi a7b5a2fbc3
Add docs to otel_ctx and otel_baggage 2024-02-04 15:44:27 +01:00
Andrea Leopardi 36042204e9
Update apps/opentelemetry_api/src/otel_span.erl
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2024-02-04 15:14:53 +01:00
Andrea Leopardi 196a7878f9
Update apps/opentelemetry_api/src/otel_span.erl
Co-authored-by: Tristan Sloughter <tristan@sloughter.dev>
2024-02-04 15:14:47 +01:00
Tristan Sloughter ecef0f404c
support for cumulative explicit histograms 2024-02-04 04:46:27 -07:00
Andrea Leopardi bc62f5d1f3
Add docs to half of the functions in otel_span 2024-02-03 20:03:36 +01:00
Tristan Sloughter 63a75e1217
expand sync_delta_histogram test to match supplementary guide 2024-02-03 05:04:23 -07:00
Tristan Sloughter 19ea063a5f
github ci: remove force mix install of rebar3 2024-02-03 04:08:54 -07:00
Tristan Sloughter 9d5458ee0d
cleanup dialyzer and eqwalizer issues 2024-02-03 04:06:56 -07:00
Tristan Sloughter 0cf3a8abde
ets:lookup_element/4 only available in 26+ so wrap in macro 2024-02-03 04:06:56 -07:00
Tristan Sloughter b5efa6c379
delete previous generations metrics 2024-02-03 04:06:55 -07:00
Tristan Sloughter f683ce5409
eqwalizer: fix reason for ignoring error on state record in reader 2024-02-03 04:06:55 -07:00
Tristan Sloughter 728a42bdcd
update eqwalizer ignores
now in experimental we don't add all the matchspec types to the records
used in ets queries but instead use eqwalizer ignore comments above
anywhere the matchspec is used.

This allows for better typing of the actual values of the records
and eases the typing of the places that use those values, like
when a sum_aggregation record is extracted to a datapoint.
2024-02-03 04:06:55 -07:00
Tristan Sloughter f442fd3e8f
update rest of metric tests for deltas being dropped between collections 2024-02-03 04:06:55 -07:00
Tristan Sloughter 01e9933399
generation based metric deltas: support restart of reader 2024-02-03 04:06:55 -07:00
Tristan Sloughter 43cb396220
update last_value aggregation to use generation 2024-02-03 04:06:54 -07:00
Tristan Sloughter ab2b089d42
explicit histogram: update to call checkpoint in collect 2024-02-03 04:06:54 -07:00
Tristan Sloughter a63959dbb3
sum agg: remove unused last_start_time from sum aggregation 2024-02-03 04:06:54 -07:00
Tristan Sloughter 1ec5e4236c
take collection start times in aggregation functions 2024-02-03 04:06:54 -07:00
Tristan Sloughter a35a43ba08
move metric checkpointing out of reader in case aggregation doens't need it 2024-02-03 04:06:54 -07:00
Tristan Sloughter fcf3f5408d
sum collect: remove unneeded variable matches in match spec 2024-02-03 04:06:53 -07:00
Tristan Sloughter 62a7ee84ab
use forget element on view_aggregation to know to use Generation 2024-02-03 04:06:53 -07:00
Tristan Sloughter 35b0132f4d
drop metrics for observables that aren't recorded in a cycle 2024-02-03 04:06:53 -07:00
Tristan Sloughter da72cb75d4
add test of cumulative async attribute removal 2024-02-03 04:06:53 -07:00
Tristan Sloughter bd63da0e74
start of using generation to lock writes during each reader checkpoint 2024-02-03 04:06:53 -07:00
Fred Hebert 366608823b
Merge pull request #679 from open-telemetry/renovate/codecov-codecov-action-4.x
chore(deps): update codecov/codecov-action action to v4
2024-02-01 10:43:54 -05:00
renovate[bot] 1d83b5f94c
chore(deps): update codecov/codecov-action action to v4 2024-01-31 18:52:04 +00:00
Fred Hebert a31d0e527e
Merge pull request #678 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.93.0
2024-01-27 10:29:25 -05:00
renovate[bot] b5977f3719
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.93.0 2024-01-25 22:03:58 +00:00
Andrea Leopardi 59fc3b3638 Address review comments 2024-01-22 16:24:37 +01:00
Andrea Leopardi ce432bb1a6
Document opentelemetry:get_tracer/* functions 2024-01-22 12:14:05 +01:00
Andrea Leopardi d5fe7e00fc
Add docs to *_processor modules 2024-01-22 12:12:47 +01:00
Bryan Naegele 99e3eec90a
Merge pull request #673 from open-telemetry/renovate/actions-cache-4.x
chore(deps): update actions/cache action to v4
2024-01-17 11:40:09 -07:00
renovate[bot] 05a770402f
chore(deps): update actions/cache action to v4 2024-01-17 17:12:13 +00:00
Bryan Naegele 26aa29920e
Merge pull request #672 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.92.0
2024-01-17 10:12:01 -07:00
renovate[bot] da4de0120e
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.92.0 2024-01-10 22:12:02 +00:00
Fred Hebert 977dcb1e8b
Merge pull request #664 from open-telemetry/renovate/actions-setup-python-5.x
chore(deps): update actions/setup-python action to v5
2023-12-15 14:05:52 -05:00
renovate[bot] 0d2810e503
chore(deps): update actions/setup-python action to v5 2023-12-15 16:42:24 +00:00
Fred Hebert 6f2d7dbe43
Merge pull request #666 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.91.0
2023-12-15 11:41:58 -05:00
renovate[bot] d853cfa293
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.91.0 2023-12-15 16:39:13 +00:00
Fred Hebert 577fa242c4
Merge pull request #665 from open-telemetry/renovate/ex_doc-0.x
chore(deps): update dependency ex_doc to ~> 0.31
2023-12-15 11:38:58 -05:00
renovate[bot] f148a4157a
chore(deps): update dependency ex_doc to ~> 0.31 2023-12-15 15:54:57 +00:00
Bryan Naegele 80003debb8
Merge pull request #667 from open-telemetry/bryannaegele-patch-1
Pin labeler to v4
2023-12-15 08:54:27 -07:00
Bryan Naegele 11dbe9195d
Update labeler.yml 2023-12-13 10:44:17 -07:00
Bryan Naegele b5939518d2
Merge pull request #663 from open-telemetry/renovate/otel-opentelemetry-collector-contrib-0.x
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.90.1
2023-12-02 19:54:32 -07:00
renovate[bot] 5225d4b75e
chore(deps): update otel/opentelemetry-collector-contrib docker tag to v0.90.1 2023-12-02 02:36:50 +00:00
Tristan Sloughter cbce85f64b
Merge pull request #632 from albertored/spec-compliance
Improve spec compliance
2023-11-22 03:30:37 -07:00
Tristan Sloughter 750e47a366
Merge branch 'main' into spec-compliance 2023-11-21 03:44:23 -07:00
Bryan Naegele 311948ac2a
Merge pull request #660 from tsloughter/collector-0.89
Collector 0.89
2023-11-20 08:53:26 -07:00
Tristan Sloughter 45e42210fb bump proto to 1.0.0 (no generated code changes) 2023-11-20 08:49:34 -07:00
Tristan Sloughter ca1191ce69 update collector to 0.89 and fix jaeger collector config for it 2023-11-20 08:49:34 -07:00
Tristan Sloughter c48e16ef0e update exporter proto instructions 2023-11-20 08:49:34 -07:00
Tristan Sloughter 78911eb53e
Merge branch 'main' into spec-compliance 2023-11-20 07:02:46 -07:00
Tristan Sloughter b5764e61c1
Merge pull request #605 from albertored/exporter-user-agent
Add User-Agent header to exporter requests
2023-11-20 02:06:55 -07:00
Alberto Sartori 0bf88c24db Add User-Agent header to exporter requests
Fixes #473
2023-11-20 09:13:15 +01:00
Tristan Sloughter b94ff50189
Merge branch 'main' into spec-compliance 2023-11-19 04:10:51 -07:00
Tristan Sloughter a79a39f44b
Merge pull request #648 from SergeTupchiy/fix-metrics-timestamp-follow-up-fix
fix(otel_otlp_metrics): convert histogram timestamps and fix 'unix_nano' field names
2023-11-19 04:06:28 -07:00
Tristan Sloughter 02786fa496
Merge branch 'main' into fix-metrics-timestamp-follow-up-fix 2023-11-19 04:04:29 -07:00
Bryan Naegele 41c793c827
Merge pull request #656 from open-telemetry/renovate/ubuntu-22.x
chore(deps): update dependency ubuntu to v22
2023-11-18 17:45:24 -07:00
Bryan Naegele 1ea1901bd6
Update w3c_interop.yml 2023-11-18 17:43:33 -07:00
renovate[bot] feb73c43bb
chore(deps): update dependency ubuntu to v22 2023-11-19 00:37:55 +00:00
Bryan Naegele ee9abcab6b
Merge pull request #659 from tsloughter/bump-grpcbox
bump grpcbox dep to 0.17.0
2023-11-18 17:37:40 -07:00
Tristan Sloughter e3cd687393 bump grpcbox to 0.17.1 2023-11-18 17:35:16 -07:00
Tristan Sloughter 070528a723 bump grpcbox dep to 0.17.0 2023-11-18 17:35:16 -07:00
Bryan Naegele afe55cd98b
Merge pull request #658 from open-telemetry/otp-workflow-versions
Set specific otp versions
2023-11-18 17:34:39 -07:00
Bryan Naegele 64053a38e0 Update api cover deps 2023-11-18 17:32:04 -07:00
Bryan Naegele 50406bc20c Update mix.exs 2023-11-18 17:32:04 -07:00
Bryan Naegele 41d391932b Update elixir.yml 2023-11-18 17:32:04 -07:00
Bryan Naegele d024b6c99f Update elixir.yml 2023-11-18 17:32:04 -07:00
Bryan Naegele a899ca290c Update elixir.yml 2023-11-18 17:32:04 -07:00
Bryan Naegele 7384a31da9 Update erlang.yml 2023-11-18 17:32:04 -07:00
Bryan Naegele 25e6fec2a4 Set specific otp versions 2023-11-18 17:32:04 -07:00
Tristan Sloughter f0021c81d1
Merge pull request #646 from tsloughter/limit-processor-pterm
create unique processor name in otel_tracer_server
2023-11-18 03:45:31 -07:00
Tristan Sloughter e878a9a209
Merge branch 'main' into limit-processor-pterm 2023-11-18 03:40:23 -07:00
Bryan Naegele a258bbca75
Merge pull request #657 from open-telemetry/renovate/mikepenz-action-junit-report-4.x
chore(deps): update mikepenz/action-junit-report action to v4
2023-11-17 13:04:12 -07:00
renovate[bot] ba8d1c7df0
chore(deps): update mikepenz/action-junit-report action to v4 2023-11-16 19:02:15 +00:00
Bryan Naegele f22876c74c
Merge pull request #655 from open-telemetry/renovate/actions-setup-python-4.x
chore(deps): update actions/setup-python action to v4
2023-11-16 10:54:47 -07:00
renovate[bot] 7b36247e67
chore(deps): update actions/setup-python action to v4 2023-11-16 17:51:18 +00:00
Bryan Naegele 2f1a5dfa1f
Merge pull request #650 from open-telemetry/renovate/ex_doc-0.x
chore(deps): update dependency ex_doc to == 0.30.9
2023-11-16 10:50:59 -07:00
Bryan Naegele 3abf69f44a
Update mix.exs 2023-11-16 10:29:34 -07:00
renovate[bot] fde471bd61
chore(deps): update dependency ex_doc to == 0.30.9 2023-11-16 17:25:53 +00:00
Bryan Naegele c3d9b455a8
Merge pull request #654 from open-telemetry/renovate/actions-checkout-4.x
chore(deps): update actions/checkout action to v4
2023-11-16 10:25:26 -07:00
renovate[bot] 7579d5f4a1
chore(deps): update actions/checkout action to v4 2023-11-16 17:24:11 +00:00
Bryan Naegele 1a6fa1a2b1
Merge pull request #653 from open-telemetry/renovate/actions-cache-3.x
chore(deps): update actions/cache action to v3
2023-11-16 10:23:36 -07:00
renovate[bot] 8f801ebd7c
chore(deps): update actions/cache action to v3 2023-11-16 17:23:27 +00:00
Bryan Naegele 837a5e955f
Merge pull request #649 from open-telemetry/renovate/cmark-0.x
chore(deps): update dependency cmark to ~> 0.10
2023-11-16 10:22:50 -07:00
renovate[bot] b7eccc5b8e
chore(deps): update dependency cmark to ~> 0.10 2023-11-15 20:19:45 +00:00
Bryan Naegele c4caa16863
Merge pull request #647 from open-telemetry/renovate/configure
Configure Renovate
2023-11-15 13:19:03 -07:00
Bryan Naegele 86a322116f
Update renovate.json 2023-11-15 13:18:41 -07:00
Serge Tupchii ed77591aa9 fix(otel_otlp_metrics): convert histogram timestamps and fix 'unix_nano' field names 2023-11-10 21:51:08 +02:00
renovate[bot] 63ce53e247
Add renovate.json 2023-11-09 14:40:59 +00:00
Tristan Sloughter d4d5c2102b
create unique processor name in otel_tracer_server
Each processor needs a unique name to reference but always creating
it in start_link means everytime the process restarts it creates
a new atom and new persistent term key. This is a leak. This patch
moves the atom creation to otel_tracer_server so it is only done once.
2023-11-06 11:34:39 -07:00
Alberto Sartori 44bc2a16a7 No more needed to check for pos numbers in sum aggregation 2023-11-05 14:41:46 +01:00
Alberto Sartori 9e02f4b67f Update changelog 2023-11-05 14:41:46 +01:00
Alberto Sartori 0e5ae107bf Changelog 2023-11-05 14:41:46 +01:00
Alberto Sartori 4027fc04e2 counter.add and histo.record should accept only positive numbers 2023-11-05 14:41:46 +01:00
Alberto Sartori 96ef35d8b3 attributes optional in counter.add and histo.record function 2023-11-05 14:41:46 +01:00
Bryan Naegele 0ec0e86321
Merge pull request #641 from SergeTupchiy/fix-processor-kill-runner
fix(otel_processor): wait for runner process termination
2023-10-29 17:42:36 -06:00
Serge Tupchii 3b243986e2 fix(otel_processor): wait for runner process termination 2023-10-29 21:32:17 +02:00
Bryan Naegele 0fb4e6c891
Merge pull request #635 from SergeTupchiy/fix-batch-processor-max-queue-size
fix(otel_batch_processor): don't divide `max_queue_size` by word-size
2023-10-29 09:28:22 -06:00
Serge Tupchii 22f3417722 fix(otel_batch_processor): start check_table_size timeouts 2023-10-29 09:18:30 -06:00
Serge Tupchii c00cffe135 fix(otel_batch_processor): don't divide `max_queue_size` by word-size
There is no need to convert `max_queue_size` to words,
as it is compared with the number of objects in ETS table.
2023-10-29 09:18:30 -06:00
Tristan Sloughter b51f206c0a
Merge pull request #644 from SergeTupchiy/fix-metrics-timestamp
fix(otel_metrics): use `opentelemetry:timestamp/0`
2023-10-28 09:01:38 -06:00
Serge Tupchii d3ab7c18fe fix(otel_metrics): use `opentelemetry:timestamp/0` (native unit monotonic time)
Timestamps are converted to Unix nano timestamps by the exporter.
2023-10-24 15:28:38 +03:00
Bryan Naegele 363d277ede
Merge pull request #640 from filmor/patch-1
Fix transmitted time units for logs
2023-10-16 21:38:08 -06:00
Benedikt Reinartz cc2e4a4eff
Fix transmitted time units for logs 2023-10-14 18:38:06 +02:00
Tristan Sloughter 2c45b1b8dc
Merge pull request #624 from albertored/wildcard-view
Allow wildcard for view instrument name
2023-10-05 04:49:14 -06:00
Alberto Sartori abe5fa0bf2 Update changelog 2023-10-03 17:07:33 +02:00
Alberto Sartori 710de34615 Fix type specs 2023-10-03 16:07:19 +02:00
Alberto Sartori 8149dd7ec4 remove some dialyzer ignores 2023-10-03 15:44:04 +02:00
Alberto Sartori f9cda55b87 Allow wildcard for view instrument name 2023-10-03 15:39:16 +02:00
Tristan Sloughter bfa5a5236b
Merge pull request #623 from albertored/metrics-query-performance
Improve ets queries performance
2023-10-02 15:11:15 -06:00
Alberto Sartori 0a4f0f24b8 fix 2023-10-02 14:23:26 +02:00
Tristan Sloughter 4af6e9e650
Merge branch 'main' into metrics-query-performance 2023-10-02 04:47:30 -06:00
Tristan Sloughter 46e690cbe0
Merge pull request #630 from albertored/flaky-test
Fix flaky test
2023-10-02 04:45:38 -06:00
Tristan Sloughter 0806073e2e
Merge branch 'main' into flaky-test 2023-10-02 04:37:48 -06:00
Tristan Sloughter 623a1fef8e
Merge pull request #628 from albertored/advisory-parameters
Support explicit_bucket_boundaries advisory parameters
2023-10-02 04:37:39 -06:00
Alberto Sartori e4d4d3d686 Fix flaky test 2023-10-02 12:27:33 +02:00
Alberto Sartori 73ac37fb01
Update apps/opentelemetry_experimental/src/otel_aggregation_last_value.erl
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2023-10-02 11:15:08 +02:00
Alberto Sartori 8c09768bc1 Add Changelog 2023-10-02 09:26:00 +02:00
Alberto Sartori 5e48148cbc Rename boundaries to explicit_bucket_boundaries 2023-10-02 09:22:43 +02:00
Alberto Sartori 119ab2b1e7 typo 2023-10-02 09:13:47 +02:00
Alberto Sartori 046d97c137 fix 2023-09-23 16:47:03 +02:00
Alberto Sartori 34e8271757 Add test about histogram aggregation option 2023-09-23 15:41:55 +02:00
Alberto Sartori d43a1f5de0 Use explicit_histogram_buckets if not configured in view 2023-09-19 17:00:33 +02:00
Alberto Sartori 3b406dce44 Validate advisory parameters 2023-09-19 11:51:52 +02:00
Alberto Sartori 0bdac8e6b0 Add advisory_params option to instruments 2023-09-19 08:22:49 +00:00
Tristan Sloughter a5f1d521aa
Merge pull request #627 from albertored/instrument-name-validation
Update instrument name regex as per specs version 1.2.5
2023-09-17 15:40:20 -06:00
Alberto Sartori 44a648464c Update instrument name regex as per specs version 1.2.5 2023-09-17 13:35:19 +00:00
Alberto Sartori bdc20484fe Improve ets queries performance 2023-09-04 17:47:41 +02:00
Tristan Sloughter a673c0f097
Merge pull request #620 from tsloughter/attribute-processing
move attribute processing to otel-attribute module
2023-08-31 15:23:43 -06:00
Tristan Sloughter 69573438a3
add changelog entry for moving attribute processing to otel_attributes 2023-08-31 15:21:01 -06:00
Tristan Sloughter 74c07f8de3
fix changelog entry for moving otel_attributes to the api 2023-08-31 15:21:01 -06:00
Tristan Sloughter 6ba380b70d
move attribute processing functions to otel_attributes module 2023-08-31 15:21:00 -06:00
Tristan Sloughter d88504ec4f
Merge pull request #618 from tsloughter/attributes-to-api
move attribute smodule to api
2023-08-30 04:40:08 -06:00
Tristan Sloughter d0d52dd22b
move attribute smodule to api 2023-08-29 04:43:05 -06:00
Tristan Sloughter 6d081861ae
Merge pull request #613 from albertored/temporality
Fix temporality handling
2023-08-28 11:01:46 -06:00
Alberto Sartori 1837af9997
Merge branch 'main' into temporality 2023-08-28 18:11:57 +02:00
Tristan Sloughter efc87f383b
Merge pull request #614 from albertored/fix-histo-buckets
Histogram buckets should be 1 more than boundaries
2023-08-28 10:05:30 -06:00
Tristan Sloughter 04effcc0f7
Merge branch 'main' into fix-histo-buckets 2023-08-28 10:03:16 -06:00
Tristan Sloughter d4469387a1
Merge branch 'main' into temporality 2023-08-28 10:01:51 -06:00
Alberto Sartori 582161e121 Fix temporality handling 2023-08-28 14:10:00 +02:00
Alberto Sartori 57b6748675 Histogram buckets should be 1 more than boundaries
Adpat default boundaries to last version of the specs
2023-08-28 14:06:02 +02:00
Tristan Sloughter 3581046398
Merge pull request #615 from derekkraan/try_another_dialyzer_fix
Change `@opaque config` to `@type config` to satisfy dialyzer in project
2023-08-28 03:20:15 -06:00
Derek Kraan bb894ebc86 Change `@opaque config` to `@type config` to satisfy dialyzer in project 2023-08-28 09:15:15 +02:00
Tristan Sloughter 73b4f13deb
Merge pull request #607 from tsloughter/tracestate-support
add tracestate module and record
2023-08-27 14:25:16 -06:00
Tristan Sloughter d34817e658
fix tracestate key pattern to properly check for end of string 2023-08-27 12:50:18 -06:00
Tristan Sloughter 3014e30c15
fix up tracestate type specs and elixir test 2023-08-27 04:26:30 -06:00
Tristan Sloughter 0a36c96840
Merge branch 'main' into tracestate-support 2023-08-26 15:04:23 -06:00
Tristan Sloughter b44cdcd45f
hardcode the compiled tracestate key/value regexes 2023-08-26 10:16:07 -06:00
Tristan Sloughter 3ed777a1d9
Merge pull request #611 from albertored/update-changelog
Update changelog
2023-08-23 13:57:28 -06:00
Alberto Sartori 872962e73b
typo
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2023-08-23 20:46:37 +02:00
Alberto Sartori a16ca7973d Update changelog 2023-08-23 16:12:27 +02:00
Tristan Sloughter 9bbe0b57ea
Merge pull request #604 from albertored/experimental-fixes
Experimental fixes
2023-08-23 06:50:37 -06:00
Alberto Sartori ca16631fd9
Update apps/opentelemetry_experimental/src/otel_meter_default.erl
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2023-08-23 13:38:34 +02:00
Alberto Sartori c4060002c4 Duplicated code 2023-08-22 17:30:24 +02:00
Alberto Sartori 39f3822050 Fix dialyzer warnings 2023-08-22 17:30:24 +02:00
Alberto Sartori cb3694ed60 Validate instrument name 2023-08-22 17:30:24 +02:00
Alberto Sartori ca4f324062 Remove unused test
Unused because the CT suite name was duplicated, the same tests are covered
in the opentelemetry_experimental tests
2023-08-22 17:30:24 +02:00
Alberto Sartori 95b08e129c Remove unused export, uniform function names 2023-08-22 17:30:24 +02:00
Alberto Sartori b759334437 Add instrument_unit to view criteria 2023-08-22 17:30:24 +02:00
Alberto Sartori d81dd4edaa Easier way for creating observable instrumenters without callback 2023-08-22 17:30:24 +02:00
Alberto Sartori 84df985ed3 Typing 2023-08-22 17:30:24 +02:00
Tristan Sloughter e4c2c1099f
add tracestate module and record
tracestate is now a record with members element which are validated
when added to the tracestate.
2023-08-21 03:55:46 -06:00
Tristan Sloughter 23c49eccba
Merge pull request #606 from albertored/histogram-match-spec
Use min/max in histogram match_spec
2023-08-21 03:40:11 -06:00
Alberto Sartori d1032a7723 Use min/max in histogram match_spec 2023-08-21 11:02:27 +02:00
Tristan Sloughter e7ad57e8ad
Merge pull request #599 from tsloughter/api-exp-docs
fix otel api experimental main docs page
2023-08-16 03:46:33 -06:00
Tristan Sloughter bacaa955cd
Merge branch 'main' into api-exp-docs 2023-08-16 03:44:55 -06:00
Tristan Sloughter 7f53395f85
Merge pull request #603 from tsloughter/support-otp-22
Support otp 22
2023-08-16 03:40:30 -06:00
Tristan Sloughter af08554a38
bump versions of api and sdk to 1.2.2 and 1.3.1 2023-08-15 11:30:28 -06:00
Tristan Sloughter 5ae85051a3
update readme requirements section 2023-08-15 11:11:27 -06:00
Tristan Sloughter 4472b96231
bump eqwalizer version to support otp-26 2023-08-15 05:00:40 -06:00
Tristan Sloughter 27a92209c5
drop otp-22 CI support because it isn't working in github actions 2023-08-15 04:53:43 -06:00
Tristan Sloughter 96a2b84834
try rebar3 3.16 for otp-22 2023-08-15 04:04:13 -06:00
Tristan Sloughter ca727008c9
move 22 in CI to an include in matrix 2023-08-15 04:01:20 -06:00
Tristan Sloughter 3a32fa374d
clear github ci cache and set rebar3 to an earlier version 2023-08-14 15:35:38 -06:00
Tristan Sloughter c522d28f7a
add otp 22 and 23 to github ci 2023-08-14 10:25:43 -06:00
Tristan Sloughter a64d65fd1f
rm use of -deprecated to support OTP-22 2023-08-14 10:19:43 -06:00
Tristan Sloughter eb89b35029
fix otel api experimental main docs page 2023-07-07 13:23:43 -06:00
Tristan Sloughter b409a5fa8e
Merge pull request #598 from tsloughter/bump-otlp-0.20.0
bump otlp protos to 0.20.0
2023-06-23 05:16:22 -06:00
Tristan Sloughter baccb2ea24
bump cache key in dialyzer tasks 2023-06-23 05:03:06 -06:00
Tristan Sloughter 9d255b198e
update error handling and type specs per eqwalizer findings 2023-06-22 13:35:44 -06:00
Tristan Sloughter 74b4449f84
bump otlp exporter version to 1.6.0 2023-06-21 15:05:46 -06:00
Tristan Sloughter 5ffda60498
add logs service pb to cover excluded mods 2023-06-21 05:27:50 -06:00
Tristan Sloughter c72bb0385f
update changelog for otlp 0.20.0 upgrade 2023-06-21 05:27:34 -06:00
Tristan Sloughter b1bb4fe030
bump otlp protos to 0.20.0 2023-06-20 15:43:55 -06:00
Tristan Sloughter 015cdcbfbc
Merge pull request #596 from tsloughter/kv-list-config
only split on first leading '=' in parsing key/value list config
2023-06-04 04:57:04 -06:00
Tristan Sloughter a2c40d9890
only split on first leading '=' in parsing key/value list config 2023-05-28 05:17:08 -06:00
Tristan Sloughter dc77e6fe2f
Merge pull request #593 from tsloughter/exp-0.4.0
bump experimental api and sdk to 0.4.0
2023-05-24 16:25:18 -06:00
Tristan Sloughter f5909ba068
bump experimental api and sdk to 0.4.0 2023-05-24 15:07:52 -06:00
Tristan Sloughter 34630debe9
Merge pull request #592 from tsloughter/id3as-main
cumulative sums fix
2023-05-21 05:03:29 -06:00
Tristan Sloughter af9f9ceac8
add test of cumulative counter multiple collects 2023-05-20 14:46:07 -06:00
Tristan Sloughter 99e1d806b1
sum agg: add match on previous_checkpoint in select_replace 2023-05-20 14:40:34 -06:00
Steve Strong 3d444079c7
For cumulative sums, actually accumulate 2023-05-20 13:18:05 -06:00
Tristan Sloughter 9c5b3a0e0b
Merge pull request #591 from tsloughter/exporter-httpc-profile
exporter: only start inets httpc profile if it doesn't exist
2023-05-19 17:00:38 -06:00
Tristan Sloughter 95ccd4ea3c
otlp exporter: bump version to 1.5.0 2023-05-19 15:34:45 -06:00
Tristan Sloughter 80881f1ed5
exporter: only start inets httpc profile if it doesn't exist 2023-05-19 11:27:30 -06:00
Tristan Sloughter 34ca33a41e
Merge pull request #589 from tsloughter/otp-26-rebar3-3.20
bump rebar3 and OTP versions in CI
2023-05-17 18:16:16 -06:00
Tristan Sloughter f4d151ffab
bump rebar3 and OTP versions in CI 2023-05-17 15:43:11 -06:00
Tristan Sloughter 6d8f8c642b
Merge pull request #575 from tsloughter/eqwalizer-actions
add eqWAlizer to github actions
2023-05-13 10:25:27 -06:00
Tristan Sloughter f6a258b6d2
Merge branch 'main' into eqwalizer-actions 2023-05-13 04:55:29 -06:00
Tristan Sloughter adc3401ecf
Merge pull request #586 from tsloughter/ex-meter-scope
get meter for application instrmentation scope in Elixir macros
2023-05-11 10:53:21 -06:00
Tristan Sloughter 932f323eef
elixir metrics tests: setup a simple processor with no exporter
This prevents warnings from being output in the test logs about
not being able to connect to an OTLP endpoint because it will
default to trying to use a localhost collector for traces.
2023-05-11 10:46:39 -06:00
Tristan Sloughter 8cb4f3836f
run mix format 2023-05-10 18:06:38 -06:00
Tristan Sloughter 0e6f57b55f
add Elixir UpDownCounter test 2023-05-10 16:58:21 -06:00
Tristan Sloughter 77be15a65f
add first Elixir metric test 2023-05-10 16:17:10 -06:00
Tristan Sloughter a4aaf0a619
get meter for application instrmentation scope in Elixir macros 2023-05-10 12:39:35 -06:00
Tristan Sloughter ca03dd17e5
Merge pull request #581 from tsloughter/metrics-resource
metrics: get the Resource from the Provider/server when registering a Reader
2023-05-09 15:04:55 -06:00
Tristan Sloughter 98012eb047
Merge branch 'main' into metrics-resource 2023-05-05 15:45:13 -06:00
Tristan Sloughter 8020bc2e91
Merge pull request #583 from id3as/main
Changed a couple of include_lib directives to include
2023-05-05 15:44:23 -06:00
Tristan Sloughter 84b1afb5cf
metrics: fix test to use same Meter in macros and non-macros 2023-05-05 12:01:18 -06:00
Tristan Sloughter 1fc3bc54d9
metrics: use application name/vsn for Meter scope 2023-05-03 19:32:45 -06:00
Tristan Sloughter 5611d68227
metrics: use ets:match instead of ets:lookup_element
This way if an instrument doesn't exist the query doesn't throw
an exception but just returns an empty list.
2023-05-03 16:42:34 -06:00
Tristan Sloughter 34473d7557
metrics: return the Resource when a Reader registers with a Provider 2023-05-03 14:26:05 -06:00
Tristan Sloughter b79c53388e
convert internal temporality atoms to proto atoms 2023-05-03 14:26:05 -06:00
Tristan Sloughter 7a41e5b30b
update metrics console exporter to latest exporter spec 2023-05-03 14:26:05 -06:00
Steve Strong 04f2b8ea54 Changed a couple of include_lib directives to include 2023-05-03 10:31:30 +01:00
Tristan Sloughter 4bef26e883
Merge pull request #578 from tsloughter/exporter-bump-1.4.1
exporter: relax constraints on API and SDK and bump vsn
2023-04-27 19:07:28 -06:00
Tristan Sloughter c7dbd6827c
exporter: relax constraints on API and SDK and bump vsn 2023-04-26 15:06:51 -06:00
Tristan Sloughter a0f5add2fb
add eqWAlizer to github actions 2023-04-22 10:35:08 -06:00
Tristan Sloughter eafe427352
Merge pull request #574 from tsloughter/sdk-disabled
add support for OTEL_SDK_DISABLED environment variable
2023-04-19 04:44:53 -06:00
Tristan Sloughter 64fecd2c4b
sdk disabled: add changelog entry 2023-04-18 18:02:10 -06:00
Tristan Sloughter 00f35aa1d6
sdk disabled: skip unneed steps in app bootup if disabled 2023-04-18 18:00:45 -06:00
Tristan Sloughter b5748619f6
add support for OTEL_SDK_DISABLED environment variable 2023-04-18 17:56:41 -06:00
Tristan Sloughter 3bf392bf4e
Merge pull request #572 from tsloughter/eqwalizer-experimental-apps
resolve eqwalizer warnings in experimental applications
2023-04-11 17:55:00 -06:00
Tristan Sloughter c85042c4a0
make aggregation typespecs easier to read with a match_spec type 2023-04-11 15:48:28 -06:00
Tristan Sloughter 92dbcd5cf4
resolve eqwalizer warnings in experimental applications 2023-04-10 16:10:22 -06:00
Tristan Sloughter 277d7c2623
Merge pull request #571 from tsloughter/eqwalizer-04-07-2023
update api, sdk and otlp exporter apps to pass eqwalizer checks
2023-04-10 16:10:10 -06:00
Tristan Sloughter 5427dec86e
fix spec of otel_span_limits:set to take a configuration map
I swear eqwalizer failed on this and its why I had changd it to
take a specific map of the keys the configuration needed to call
span_limits:set... but after trying to make an example to show
the issue I wasn't able to reproduce, went back, changed it back
to configuration:t() and it works.
2023-04-09 10:34:06 -06:00
Tristan Sloughter 95785c2b50
remove unknown warnings from mix dialyzer
this is to deal with it warning about use of eqwalizer:dynamic()
type. Won't be an issue when we move to OTP-26+ and the dynaimc()
type is builtin.
2023-04-09 05:24:37 -06:00
Tristan Sloughter 2fd5fda6f5
fixup exporter endpoint input and state typing for dialyzer/eqwalizer 2023-04-09 05:10:51 -06:00
Tristan Sloughter 4b14b3f6d6
fix dialyzer warnings
The only ones I'm not sure of are the nowarn_functions in
opentelemetry_app that are needed because it doesn't like the
type spec of otel_span_limits:set/1.

`set` takes a configuration but specs and matches on only a
portion of it, I guess dialyzer doesn't like that.
2023-04-08 11:54:53 -06:00
Tristan Sloughter 1b2a1e1580
update api, sdk and otlp exporter apps to pass eqwalizer checks 2023-04-08 11:43:44 -06:00
Tristan Sloughter 491e5530c1
Merge pull request #569 from tsloughter/terminate-noop-default
Resource as an argument to starting the tracer provider
2023-04-05 15:47:02 -06:00
Tristan Sloughter b2da332ce2
ignore elixir dialyzer warning about otel_tracer_provider_sup:start/2 2023-04-05 06:59:36 -06:00
Tristan Sloughter b7d90b9668
keep a test of the deprecated opentelemetry:start_tracer_provider function 2023-04-05 06:51:09 -06:00
Tristan Sloughter 2300d09990
update meterprovider to take resource as an argument on start 2023-04-04 17:55:53 -06:00
Tristan Sloughter 6d71b717ac
move tracerprovider to the SDK only
this better follows the spec
2023-04-03 16:46:59 -06:00
Tristan Sloughter 62f6c94a8e
update changelog 2023-04-02 16:18:47 -06:00
Tristan Sloughter 2b4107b46a
set default tracer to noop in API tests 2023-04-02 15:12:34 -06:00
Tristan Sloughter 26f5506e68
test after SDK shutdown the API still works but returns the 0'ed spans
Instead of setting the global tracer to noop on shutdown of the SDK
we rely on the fact the API already handles the SDK being gone.

Not setting the tracer to noop saves a global GC from the persistent
term update that could negatively impact users.
2023-04-02 15:12:27 -06:00
Tristan Sloughter 657c9a3e9c
make Resource an argument to the tracer provider 2023-04-02 15:12:18 -06:00
Tristan Sloughter a203823315
Merge pull request #568 from tsloughter/sampler-attributes
Add tests of an example sampler based on attributes
2023-04-02 15:07:54 -06:00
Tristan Sloughter b66d8141e2
add writes permission for junit report action 2023-04-02 11:07:29 -06:00
Tristan Sloughter 237109b349
try publishing junit report from erlang workflow 2023-04-02 05:45:11 -06:00
Tristan Sloughter 462de59ac8
attributes sampler: use smaller map for iterator 2023-04-02 05:17:51 -06:00
Tristan Sloughter c82a389b01
remove use of maps:iterator in example/test attributes sampler 2023-04-01 04:54:35 -06:00
Tristan Sloughter 2d587cf04d
run mix format at top level for mix.exs 2023-03-31 18:10:50 -06:00
Tristan Sloughter 99da6bee9b
add a test that application stop of SDK flushes spans 2023-03-31 18:10:50 -06:00
Tristan Sloughter 3b2271810d
add otel_resource module doc to otel_resource 2023-03-31 18:10:50 -06:00
Tristan Sloughter f9a81238fc
fix attribute_value type to include tuple() for arrays 2023-03-31 18:10:50 -06:00
Tristan Sloughter 1946a68714
add test sampler that compares attributes
This was mainly done to test the example code to be used on
opentelemetry.io for Sampler docs but it also does do some
useful testing of the sampler and provides some example code.
2023-03-31 18:10:49 -06:00
Tristan Sloughter 3497c6db77
Merge pull request #555 from marcdel/span-status-docs
documents valid span statuses
2023-03-23 05:09:10 -06:00
Tristan Sloughter 588512b337
Merge branch 'main' into span-status-docs 2023-03-23 05:00:27 -06:00
Tristan Sloughter 6a53aaf87d
Merge pull request #556 from marcdel/ci
looks like strict option wants to be on erlef/setup-beam not top level
2023-03-23 04:56:04 -06:00
Tristan Sloughter 7e7a725985
Merge branch 'main' into ci 2023-03-23 04:53:04 -06:00
Tristan Sloughter efb7400c49
Merge pull request #567 from tsloughter/exception-test
fix Elixir record_exception top level test
2023-03-23 04:52:45 -06:00
Tristan Sloughter fe59ecde0b
fix Elixir record_exception top level test 2023-03-22 15:23:06 -06:00
Tristan Sloughter 010a2ad455
Merge branch 'main' into ci 2023-03-22 12:16:10 -06:00
Tristan Sloughter 2471336abb
Merge pull request #566 from tsloughter/format-mix-exs
run mix format at top level for mix.exs
2023-03-22 12:15:53 -06:00
Tristan Sloughter 9ade1f3769
Merge branch 'main' into span-status-docs 2023-03-22 10:28:04 -06:00
Tristan Sloughter eb467e7c18
run mix format at top level for mix.exs 2023-03-22 10:27:23 -06:00
Tristan Sloughter 174ad95145
Merge branch 'main' into ci 2023-03-22 10:23:18 -06:00
Tristan Sloughter f7a9489bdf
Merge pull request #565 from tsloughter/fix-otel-tests-ex
fix top level elixir test by adding semconv dep
2023-03-22 10:22:54 -06:00
Tristan Sloughter afd03f57be
fix top level elixir test by adding semconv dep 2023-03-22 04:58:26 -06:00
Tristan Sloughter 96f8efb402
Merge branch 'main' into ci 2023-03-22 04:44:20 -06:00
Tristan Sloughter eb784e167e
Merge pull request #564 from tsloughter/test-fix
fix a couple tests
2023-03-22 04:17:52 -06:00
Tristan Sloughter 3e971fb252
metrics exporter test: fix aggregation temporality atom 2023-03-21 18:50:12 -06:00
Tristan Sloughter 3e1222fbad
api test: fix test that relied on maps:keys being sorted 2023-03-21 18:50:12 -06:00
Tristan Sloughter 9711886036
Merge branch 'main' into ci 2023-03-21 17:44:55 -06:00
Tristan Sloughter 3a51a01d4d
Merge pull request #551 from Cantido/semconv-to-functions
Elixir semcomv: use functions instead of macros
2023-03-21 17:28:58 -06:00
Tristan Sloughter dde9cb0e79
Merge branch 'main' into ci 2023-03-21 16:24:56 -06:00
Tristan Sloughter 8b2a9905c5
Merge branch 'main' into span-status-docs 2023-03-21 16:24:12 -06:00
Tristan Sloughter 6ba75492b2
Merge branch 'main' into semconv-to-functions 2023-03-21 16:16:17 -06:00
Tristan Sloughter de8ddc0103
Merge pull request #561 from tsloughter/multi-result-observable
metrics: fix observable callbacks to return a list of results
2023-03-21 16:15:58 -06:00
Tristan Sloughter 797c72649d
Merge branch 'main' into multi-result-observable 2023-03-21 16:06:58 -06:00
Tristan Sloughter f42c8e4598
Merge branch 'main' into semconv-to-functions 2023-03-21 16:06:27 -06:00
Tristan Sloughter 8058414c9c
Merge branch 'main' into ci 2023-03-21 15:56:20 -06:00
Tristan Sloughter 4812195bfa
Merge pull request #562 from tsloughter/sdk-v1.3.0
bump sdk to 1.3.0
2023-03-21 09:05:35 -06:00
Tristan Sloughter 9288c57fa6
bump sdk to 1.3.0 2023-03-21 05:08:59 -06:00
Tristan Sloughter 8e169813e9
metrics: fix observable callbacks to return a list of results
the instrument could have a result for multiple sets of attributes,
so a list of observations must be returned in every case.
2023-03-20 18:19:01 -06:00
Tristan Sloughter 79828e92eb
Merge pull request #559 from Whatnot-Inc/fix/swap-tables
Fix swapping exporter tables
2023-03-20 13:29:07 -06:00
Rafal Studnicki 98df391f71 Swap tables correctly when exporting 2023-03-20 17:15:50 +01:00
Tristan Sloughter cf9f2d3248
Merge pull request #560 from tsloughter/delta-observables
metrics: support delta/cumulative conversions in sum aggregator
2023-03-19 05:22:16 -06:00
Tristan Sloughter f6944c3568
metrics: support delta/cumulative conversions in sum aggregator
Cumulative aggregate is now also reset on each collection. A
previous checkpoint field is tracked in order to add the current
value to the previous in the case of needing the cumulative and
subtracting in the case you have a cumulative but need a delta
(example being an Observable which reports the cumulative value
in each callback and needed it reported as a delta).
2023-03-17 17:28:46 -06:00
Marc Delagrammatikas fd45990f30 document the span attribute that this actually sets 2023-03-11 13:18:30 -08:00
Marc Delagrammatikas f57f0e0cdc include :error in the OpenTelemetry.status documentation 2023-03-11 13:17:22 -08:00
Marc Delagrammatikas 3e3c982995 remove `:unset` as a valid param value 2023-03-11 13:07:31 -08:00
Marc Delagrammatikas d9b480ddc6 looks like strict option wants to be on erlef/setup-beam not top level 2023-03-10 14:36:39 -08:00
Marc Delagrammatikas c47bf9b7d7
documents valid span statuses 2023-03-10 13:02:48 -08:00
Rosa Richter 7bcff34012
Elixir: use functions instead of macros 2023-03-09 17:13:33 -07:00
Tristan Sloughter 1f024191a6
Merge pull request #553 from tsloughter/view-attr-filter
metric views: support filtering attributes
2023-03-09 16:54:02 -07:00
Tristan Sloughter b42e112106
Merge branch 'main' into view-attr-filter 2023-03-09 14:59:53 -07:00
Tristan Sloughter 6cf68f6845
Merge pull request #549 from tsloughter/httpc-profile
use unique httpc profile per otlp exporter
2023-03-09 14:58:31 -07:00
Tristan Sloughter 1e318ae0dc
views: tests for attribute filtering 2023-03-07 17:55:09 -07:00
Tristan Sloughter fd6a0d10ee
views: support attribute filtering 2023-03-07 17:55:09 -07:00
Tristan Sloughter 797361b3a7
Update apps/opentelemetry_exporter/src/opentelemetry_exporter.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2023-03-04 15:07:53 -07:00
Tristan Sloughter 1faa6e3bb6
use unique httpc profile per otlp exporter 2023-03-04 11:08:36 -07:00
Tristan Sloughter 38591ea15d
Merge pull request #548 from tsloughter/bump-api-otlp-1.2.1
update versions and changelog
2023-02-22 10:15:03 -07:00
Tristan Sloughter d412c318d0
update versions and changelog 2023-02-21 13:21:17 -07:00
Tristan Sloughter 8c06ff727c
Merge pull request #547 from tsloughter/tls-cert-dialyzer
bump tls_certificate_check and some small dialyzer improvements
2023-02-20 15:56:05 -07:00
Tristan Sloughter e473e3a595
upgrade tls_certificate to 1.17.4 to resolve OTP-25 crash 2023-02-19 16:56:04 -07:00
Tristan Sloughter 4bb4e73a63
add nowarn_function around optional function calls and missing OTP types 2023-02-19 16:56:03 -07:00
Tristan Sloughter aa0294da33
add ctx to exporter applications list to satisify dialyzer 2023-02-19 16:56:03 -07:00
Tristan Sloughter cdd2d7b885
fix typespec of last_start_time_unix_nano in aggregations 2023-02-19 16:56:03 -07:00
Tristan Sloughter 7daca8ec5a
export otel_sampler:sampler_spec to be used in samplers 2023-02-19 16:56:03 -07:00
Tristan Sloughter 6a29857f39
Merge pull request #546 from tsloughter/delta-timestamps
metrics: fix updating delta timestamps in aggregations
2023-02-15 17:24:09 -07:00
Tristan Sloughter 11a25a6a21
Merge branch 'main' into delta-timestamps 2023-02-15 11:25:41 -07:00
Tristan Sloughter fd622b35d9
metrics: fix updating delta timestamps in aggregations 2023-02-15 11:16:40 -07:00
Tristan Sloughter 222e1664c1
Merge pull request #544 from tsloughter/silence-instruments
Move is_monotonic check to the SDK
2023-02-15 11:16:03 -07:00
Tristan Sloughter 4c2e721a88
improve some typing thanks to eqwalizer
This has more dialyzer ignores added in order to remove stuff like
'$1' and '_' in type specs. I figure this is acceptable because
eqwalizer has a more fine grained ignore ability which will let us
check these parts of the code better even if the dialyzer warnings
are now ignored from those parts of the code.
2023-02-07 17:33:32 -07:00
Tristan Sloughter 825bec0d74
Merge branch 'main' into silence-instruments 2023-02-07 15:43:09 -07:00
Tristan Sloughter 1f1ac7006b
Merge pull request #542 from tsloughter/eqwalizer
add support for running eqwalizer
2023-02-06 05:15:48 -07:00
Tristan Sloughter 82feb8a958
use atoms for more attribute/event key names 2023-02-06 05:14:20 -07:00
Tristan Sloughter 8e7fc909b9
use ViewAggregation to all aggregation functions 2023-02-05 15:45:46 -07:00
Tristan Sloughter dfd03d0895
handle is_monotonic for views in Sum aggregation
This required changing the aggregate API to be passed the
view_aggregation record so it has access to is_monotonic. The
API feels a little cleaner anyway.
2023-02-05 10:56:21 -07:00
Tristan Sloughter b75b68f429
fix is_monotonic to true for histogram kind instrument 2023-01-30 15:25:01 -07:00
Tristan Sloughter 7f8f743f53
remove value check and logs from instrument API 2023-01-27 15:32:47 -07:00
Tristan Sloughter a5dbd69f19
fix reader collect handling function matches caught by eqwalizer 2023-01-26 13:30:48 -07:00
Tristan Sloughter 8aa5552edc
add eqwalizer deps 2023-01-26 13:30:47 -07:00
Tristan Sloughter e0161da7c6
Merge pull request #533 from tsloughter/fix-carrier-typespec
fix typespec of text_map:carrier_get/set
2023-01-26 13:30:00 -07:00
Tristan Sloughter d608a1a704
Merge branch 'main' into fix-carrier-typespec 2023-01-26 13:29:02 -07:00
Tristan Sloughter b712cdd631
Merge pull request #541 from tsloughter/bump-tls-cert
upgrade tls_certificate to 1.17
2023-01-20 04:55:11 -07:00
Tristan Sloughter ee31132231
upgrade tls_certificate to 1.17 2023-01-19 10:24:31 -07:00
Tristan Sloughter 28fa2db594
Merge pull request #540 from Kuroneer/set-status-undefined-is-recording
Have set_status check is_recording in all cases
2023-01-17 04:42:51 -07:00
Jose M Perez 8ae3585e2e Have set_status check is_recording in all cases
?is_recording macro is missing when setting status as undefined
2023-01-17 03:30:40 +01:00
Tristan Sloughter 9bbf8f294b
Merge pull request #537 from wingyplus/exception-atom
Using opentelemetry_semantic_conventions for record_exception
2023-01-12 04:32:52 -07:00
Thanabodee Charoenpiriyakij 9582d08944
Using opentelemetry_semantic_conventions for record_exception
Use constant from opentelemetry_semantic_conventions in
record_exception instead of binary (or string in Elixir). This changes
apply to both Erlang and Elixir API.
2023-01-12 17:05:49 +07:00
Tristan Sloughter 294a05ef80
Merge pull request #535 from tsloughter/bump-sdk-1.2.1
bump sdk to 1.2.1
2023-01-09 15:08:58 -07:00
Tristan Sloughter ff8d00dd4d
bump sdk to 1.2.1 2023-01-09 11:56:55 -07:00
Tristan Sloughter 1c7c9150f0
Merge pull request #531 from Kuroneer/resource-atom-keys
Store keys for otel_resource attributes as atoms
2023-01-08 05:04:05 -07:00
Jose M Perez 2e02dd073b Store otel_resource attributes keys as atoms
Imported attribute keys (from opentelemetry_semantic_conventions) are
atoms, so otel_resource should support them.

As the resource is initialized only once and it is going to be copied
a lot, it's worth storing the provided keys as atoms to save memory.

Also, otel_resource_detector shouldn't know the type of the key, so add
an indirection level for the key check.
2023-01-08 06:02:34 +01:00
Tristan Sloughter fa3afc4409
Merge pull request #530 from tsloughter/api-experimental-0.2.0
bump experimental api dep on stable api to 1.2
2023-01-05 13:50:32 -07:00
Tristan Sloughter 1b44d57ed5
fix typespec of text_map:carrier_get/set 2023-01-05 13:49:24 -07:00
Tristan Sloughter 85bb9b4a68
bump experimental api dep on stable api to 1.2 2022-12-27 11:05:14 -07:00
Tristan Sloughter 3b7f9194cf
Merge pull request #529 from tsloughter/experimental-0.2.0
bump experimental apps to 0.2.0
2022-12-27 11:02:54 -07:00
Tristan Sloughter 14a016dd46
bump experimental apps to 0.2.0 2022-12-23 11:57:09 -07:00
Tristan Sloughter 4439929b50
Merge pull request #527 from tsloughter/cut-new-vsn
bump api, sdk and exporter to 1.2.0 and 1.3.0 respectively
2022-12-23 10:14:22 -07:00
Tristan Sloughter 20146f8626
bump api, sdk and exporter to 1.2.0 and 1.3.0 respectively 2022-12-22 14:00:26 -07:00
Tristan Sloughter 4ebb339916
Merge pull request #526 from tsloughter/cumulative-histo-checkpoint
don't checkpoint cumulative histogram
2022-12-22 12:39:58 -07:00
Tristan Sloughter a14b49e2e6
Merge branch 'main' into cumulative-histo-checkpoint 2022-12-22 12:38:47 -07:00
Tristan Sloughter 0c52e71361
Merge pull request #516 from tsloughter/rm-value-type
remove value_type from instruments
2022-12-22 12:37:49 -07:00
Tristan Sloughter 979f9549d6
Merge branch 'main' into rm-value-type 2022-12-22 12:36:28 -07:00
Tristan Sloughter 7276c12e12
Merge branch 'main' into cumulative-histo-checkpoint 2022-12-22 12:36:08 -07:00
Tristan Sloughter 0227fd284f
Merge pull request #525 from tsloughter/semconv-sdk
use generated semantic conventions in SDK resource detection
2022-12-22 12:34:50 -07:00
Tristan Sloughter a512334dba
add jaeger to docker-compose 2022-12-21 17:01:06 -07:00
Tristan Sloughter 78343b264c
just don't checkpoint cumulative histograms for now 2022-12-21 17:01:06 -07:00
Tristan Sloughter cd8c638176
use version:strict in github actions for setup-beam 2022-12-21 11:53:25 -07:00
Tristan Sloughter 4354842370
use generated semantic conventions in SDK resource detection 2022-12-21 10:59:54 -07:00
Tristan Sloughter 51b5907eb2
Merge pull request #519 from Kuroneer/set_status_code_only
otel_span:set_status support for status code
2022-12-19 17:44:00 -07:00
Tristan Sloughter ce9ee5398c
Update apps/opentelemetry_experimental/test/otel_metrics_SUITE.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-12-19 14:49:23 -07:00
Tristan Sloughter 5018832cf3
update elixir api to remove value_type 2022-12-19 14:49:23 -07:00
Tristan Sloughter 6d104518c5
support combining int and float measurements in sum aggregator 2022-12-19 14:49:23 -07:00
Tristan Sloughter 51dc60f4d6
cleanup dialyzer issues with aggregators 2022-12-19 14:49:23 -07:00
Tristan Sloughter b4851f80f7
wrap protobuf metric value in as_double/as_int 2022-12-19 14:49:23 -07:00
Tristan Sloughter 0b8f58085d
remove value_type 2022-12-19 14:49:23 -07:00
Tristan Sloughter 0047719078
bump experimental api to use beta of api package 2022-12-19 14:49:23 -07:00
Tristan Sloughter e84c53296f
include value_type for in aggregation_options 2022-12-19 14:49:22 -07:00
Tristan Sloughter 88172f096e
Merge branch 'main' into set_status_code_only 2022-12-19 14:49:00 -07:00
Tristan Sloughter 37f3cecd9a
Merge pull request #520 from tsloughter/skip-export-empty
skip export if spans is an empty list
2022-12-18 11:10:55 -07:00
Tristan Sloughter 48635f0daf
bump ubuntu versions used in github actions 2022-12-15 16:52:56 -07:00
Tristan Sloughter 476d625402
skip export if spans is an empty list 2022-12-15 16:09:59 -07:00
Jose M Perez 5d5c67bcac otel_span:set_status support for status code
The ?set_status macro in otel_tracer.hrl indicates that
otel_span:set_status/1 allows you to provide both a
opentelemetry:status() or a opentelemetry:status_code()

This commit fixes the opentelemetry:status_code() case

Also, since the typing already supports undefined, translate it to UNSET
2022-12-15 14:28:52 +01:00
Tristan Sloughter 2ed9473e97
Merge pull request #514 from tsloughter/measure-by-name
pass name, not instrument, in metric macros to record measurements
2022-12-07 14:19:30 -07:00
Tristan Sloughter f12308c094
Merge branch 'main' into measure-by-name 2022-12-07 10:04:17 -07:00
Tristan Sloughter 66ea38628b
Merge pull request #513 from bullno1/preserve-tuple-attribute-value
Preserve a tuple attribute value
2022-12-07 04:44:28 -07:00
Tristan Sloughter d7925e74cf
Merge branch 'main' into preserve-tuple-attribute-value 2022-12-07 04:41:17 -07:00
Bach Le 08e5b28c41 Update opentelemetry_api_SUITE:validation to preserve tuple 2022-12-07 11:40:00 +08:00
Bach Le b4c1b6fdba Preserve a tuple attribute value 2022-12-07 11:30:37 +08:00
Tristan Sloughter 1ad12bb340
pass name, not instrument, in metric macros to record measurements 2022-12-06 09:29:56 -07:00
Tristan Sloughter 5f02dfe2cd
Merge pull request #511 from bullno1/propagate-tracestate
Assign tracestate from sampler to new span
2022-12-06 09:17:17 -07:00
Tristan Sloughter 39cce2efad
Merge branch 'main' into propagate-tracestate 2022-12-06 05:13:16 -07:00
Tristan Sloughter 51806945a4
Merge pull request #501 from bullno1/export-otel_ctx-token
Export otel_ctx token
2022-12-06 04:48:49 -07:00
Tristan Sloughter 31d89b78e4
Merge branch 'main' into export-otel_ctx-token 2022-12-06 04:35:03 -07:00
Bach Le b6a8315207 Revert "Make otel_ctx:extract returns the context instead of token."
This reverts commit b898c8dce3.
2022-12-06 16:19:10 +08:00
Bach Le c266264687 Assign tracestate from sampler to new span 2022-12-06 16:18:50 +08:00
Tristan Sloughter da5fc81ba7
Merge pull request #508 from tsloughter/fix-exporter-api-1.2.0-beta
fix exporter dependency on api to 1.2.0-beta
2022-12-05 15:02:55 -07:00
Tristan Sloughter 4d443028b1
fix exporter dependency on api to 1.2.0-beta 2022-12-05 12:55:33 -07:00
Tristan Sloughter d29a5156a3
Merge pull request #505 from tsloughter/1.2-beta
bump api, sdk, exporter versions to beta releases
2022-12-05 12:46:33 -07:00
Tristan Sloughter deb944716d
Merge branch 'main' into 1.2-beta 2022-12-05 12:40:17 -07:00
Tristan Sloughter efa8811ce0
Merge pull request #506 from tsloughter/fix-zipkin-build
bump zipkin to 1.1.1
2022-12-04 10:34:15 -07:00
Tristan Sloughter ef14fd2525
bump zipkin to 1.1.1 2022-12-03 11:35:26 -07:00
Tristan Sloughter b89a4e3c8b
Merge pull request #504 from maartenvanvliet/patch-1
Fix typo
2022-12-03 10:21:57 -07:00
Tristan Sloughter c677f2a063
bump api, sdk, exporter versions to beta releases 2022-12-02 15:49:55 -07:00
Maarten van Vliet 6fd27ebffb
Fix typo 2022-12-02 20:26:57 +01:00
Tristan Sloughter 389a110b41
Merge branch 'main' into export-otel_ctx-token 2022-12-01 04:59:42 -07:00
Tristan Sloughter 4ce3851b2a
Merge pull request #503 from tsloughter/add-agg-options
Include aggregation options in aggregate callback
2022-12-01 04:54:01 -07:00
Tristan Sloughter e7768c236f
add aggregation behaviour to each aggregation module 2022-11-30 11:38:13 -07:00
Tristan Sloughter 385cc39df0
fix concurrent metrics creation to not overwrite previous measurement 2022-11-30 10:34:00 -07:00
Tristan Sloughter ed3ea5ac44
update types for aggregation module functions 2022-11-29 17:17:03 -07:00
Tristan Sloughter e0cdb0bbc9
Merge pull request #502 from tsloughter/share-tables
Use the same ets tables for all Readers
2022-11-29 16:23:46 -07:00
Tristan Sloughter d04c953213
fix dialyzer errors around counters use in bucket_counts 2022-11-29 16:20:44 -07:00
Tristan Sloughter 41700d3470
histogram aggregation: match Key in MatchHead so index is used 2022-11-29 10:22:30 -07:00
Tristan Sloughter bc248959ef
concurrent update safe explicit histogram 2022-11-28 16:08:33 -07:00
Tristan Sloughter 0f7a9dbb68
rm TODO about removing Reader entries that is no longer needed
the Readers have a reference they reuse if they crash so no
need to remove their entries in tables like when they were using
the pids.
2022-11-27 12:31:16 -07:00
Tristan Sloughter f031153780
consistent naming of ets tables and its types 2022-11-27 05:10:07 -07:00
Tristan Sloughter 5e65254d4d
share callbacks table between readers 2022-11-26 13:21:31 -07:00
Tristan Sloughter 824076a2c2
use a reference to track Readers across restarts 2022-11-25 14:09:15 -07:00
Tristan Sloughter 6c67450c4f
rematch Views when a Reader is added 2022-11-25 10:55:21 -07:00
Bach Le b898c8dce3 Make otel_ctx:extract returns the context instead of token. 2022-11-26 01:41:32 +08:00
Tristan Sloughter fa72a8ed0b
remove unused Meter import from Elixir metrics API test 2022-11-25 10:00:50 -07:00
Bach Le a0c36631ab Fix type errors 2022-11-26 00:47:20 +08:00
Bach Le f8e4f1e5b2 Export otel_ctx:token/0 2022-11-26 00:38:52 +08:00
Tristan Sloughter f46126eb90
share viewaggregations and metrics ets tables between readers
to allow Readers to share tables and only 1 table be updated when
a measurement is taken, the table references are added to the  Meter
record and a Reader pid is added to view_aggregation and the key
for Metrics is extended to include the Reader pid.
2022-11-25 05:05:16 -07:00
Tristan Sloughter d0160fa6f2
Merge pull request #496 from tsloughter/metrics-macro-api
Metrics macro api
2022-11-24 11:48:43 -07:00
Tristan Sloughter 3541c151f2
resolve dialyzer issue with matchspec '_' in meter 2022-11-24 10:08:47 -07:00
Tristan Sloughter c605a68189
Merge branch 'main' into metrics-macro-api 2022-11-24 09:42:20 -07:00
Tristan Sloughter 4545d512ea
Merge pull request #499 from tsloughter/view-match-specs
inefficient use of matchspec for view matching
2022-11-24 09:42:01 -07:00
Tristan Sloughter 14cf217ca9
inefficient use of matchspec for view matching
This patch uses ets:match_spec_run to compare a single View against
a single Instrument. This is to be the smallest possible change
when moving to use of a matchspec. The more efficient version will
come with running the matchspec against the Instruments table to
find matches. Though for new Instruments the inefficient version
will remain.
2022-11-23 16:51:09 -07:00
Tristan Sloughter 878399a705
rename instrument/7 in default meter to create_insturment 2022-11-23 10:06:10 -07:00
Tristan Sloughter 4ed86cf05f
move Elixir macros for creation/update of Instruments to their own modules 2022-11-23 10:06:10 -07:00
Tristan Sloughter 3e14123064
add Elixir tests of metrics API instrument creation 2022-11-23 10:06:09 -07:00
Tristan Sloughter 34e995863d
add Elixir metrics api 2022-11-23 10:06:09 -07:00
Tristan Sloughter 1a92ce9c8e
macros for creating and recording with instruments 2022-11-23 10:06:09 -07:00
Tristan Sloughter 3a813752e1
module missing warning message didn't make sense 2022-11-23 10:06:09 -07:00
Tristan Sloughter bdc8fdfbd4
register Instruments with meter provider when created
when an Instrument is added it is matched against existing Views
to create a ViewAggregation for each match (and for each Reader).

ViewAggregations table is updated to be a bag to simplify the
updating of Instrument to ViewAggregation mapping. Now it is
just an insert for the newly matched Views if a View is added
and matches against existing Instruments.
2022-11-23 10:06:09 -07:00
Tristan Sloughter a4263b9cb7
Merge pull request #495 from tsloughter/fix-semconv-header
fix the Erlang header file generated in semconv app
2022-11-21 11:19:26 -07:00
Tristan Sloughter c5e7789033
bump semconv app to 0.2.0 2022-11-21 10:52:10 -07:00
Tristan Sloughter 493b302e4e
fix Erlang header template to end define's in periods 2022-11-21 10:51:18 -07:00
Tristan Sloughter 89c4b00b59
Merge pull request #492 from tsloughter/multi-metric-providers
Improvements to MeterProvider startup
2022-11-16 15:13:49 -07:00
Tristan Sloughter 3136b243ef
dialyzer fix: make default aggregation_option an empty map 2022-11-16 15:08:20 -07:00
Tristan Sloughter 10ec99f117
Update apps/opentelemetry_experimental/src/otel_metric_reader_sup.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-11-16 15:04:23 -07:00
Tristan Sloughter 9b45634502
make view aggregation_options a map 2022-11-16 15:04:23 -07:00
Tristan Sloughter dbcb8f9b95
don't add instrument to meter provider 2022-11-16 15:04:23 -07:00
Tristan Sloughter 3fba962155
metrics: add otel_meter_server functions that call the global provider 2022-11-16 15:04:23 -07:00
Tristan Sloughter c76b40e52f
metrics: support views defined in configuration 2022-11-16 15:04:22 -07:00
Tristan Sloughter f1ff8bdd70
fix metrics tests to use global meter provider 2022-11-16 15:04:22 -07:00
Tristan Sloughter 19ed0322dd
align Meter registration and getting with Tracers 2022-11-16 15:04:22 -07:00
Tristan Sloughter b1c6f2e318
readers add themselves to meter server
Instead of having the metric readers get started and have to get
their ets table names from the server this change makes the
readers add themselves to the server.
2022-11-16 15:04:22 -07:00
Tristan Sloughter ce29656621
Merge pull request #491 from tsloughter/docs-semconv
add docs generation for semantic conventions app
2022-11-14 16:05:27 -07:00
Tristan Sloughter 80e4c2bfb1
add docs generation for semantic conventions app 2022-11-10 05:52:43 -07:00
Tristan Sloughter 51437476b1
Merge pull request #490 from yordis/add-elixir-semantic-conventions
feat: add elixir semantic conventions
2022-11-09 17:02:07 -07:00
Tristan Sloughter e03ecf1e48
Merge branch 'main' into add-elixir-semantic-conventions 2022-11-09 16:57:25 -07:00
Yordis Prieto Lazo e9a60f0879 feat: add elixir semantic conventions 2022-11-09 17:53:31 -06:00
Tristan Sloughter f7c857af23
Merge pull request #488 from tsloughter/revive-benchee-1
the beginning of bringing benchee back
2022-11-09 12:11:16 -07:00
Tristan Sloughter 57799ce288
Merge branch 'main' into revive-benchee-1 2022-11-09 12:07:21 -07:00
Tristan Sloughter 2ff5849d01
Merge pull request #483 from tsloughter/multi-batch-processor
better support for multiple tracer providers and processors
2022-11-09 12:03:37 -07:00
Tristan Sloughter 65f1843613
Merge branch 'main' into multi-batch-processor 2022-11-09 09:07:43 -07:00
Tristan Sloughter fe2459cf29
Merge branch 'main' into revive-benchee-1 2022-11-09 09:07:33 -07:00
Tristan Sloughter bdefe105ff
Merge pull request #487 from tsloughter/semconv-hrl
add semantic conventions app with Erlang macros defining keys
2022-11-09 03:56:59 -07:00
Tristan Sloughter 8a0441356d
the beginning of bringing benchee back 2022-11-08 04:48:23 -07:00
Tristan Sloughter 4a795588bc
add semantic conventions app with Erlang macros defining keys 2022-11-07 13:30:16 -07:00
Tristan Sloughter c6f91caf2e
batch exporter: no longer rename table being exported
Until there is concurrent exporting there is no need for this.
Renaming can also mean a span is lost because it is to be
written to the table but that table then disappears. There is
still the chance this happens once the table is deleted before
being recreated, but it lessens it.
2022-11-05 13:40:00 -06:00
Tristan Sloughter bf20886bf2
remove unnecessary case statement for try ... of 2022-11-04 05:24:20 -06:00
Tristan Sloughter 7dc65760c5
add deprecated module attribute for set_exporter 2022-11-04 05:22:24 -06:00
Tristan Sloughter 7bb712d97a
remove unneeded OTEL_TRACES_EXPORTER=none env var in github erlang tests 2022-11-03 16:11:09 -06:00
Tristan Sloughter 9032729468
elixir sdk tests: fixup for removal of set_exporter 2022-11-03 15:54:24 -06:00
Tristan Sloughter 2fc91cb630
check module_info instead of function_exported to work with unloaded mods 2022-11-03 06:08:20 -06:00
Tristan Sloughter 34a609ae73
get rid of unneeded get_tracer from elixir sdk tests 2022-11-03 06:05:50 -06:00
Tristan Sloughter 3f6375dd12
use simple_processor in elixir tests 2022-11-02 17:03:29 -06:00
Tristan Sloughter 2d87b077ee
fix on_end processor to handle non-boolean returns 2022-11-02 15:54:37 -06:00
Tristan Sloughter 894e27b4f9
1 processor providers act as a global processor to allow set_exporter to work 2022-11-02 15:03:55 -06:00
Tristan Sloughter b65b442f2c
also use reference for unique name in simple_processor 2022-11-02 10:42:06 -06:00
Tristan Sloughter 853c2e1dd4
don't require a processor name and generate one if needed 2022-11-02 09:45:56 -06:00
Tristan Sloughter a1bf6e55ca
remove unneeded testcase init in ct suite 2022-11-02 04:40:11 -06:00
Tristan Sloughter fce299bc97
fix formatting in elixir file 2022-11-02 04:38:30 -06:00
Tristan Sloughter 9ddf4455b1
comment out set_exporter in simple_processor for now 2022-11-01 17:25:51 -06:00
Tristan Sloughter d58e434950
fix renaming of current_send_table in batch processor to be unique 2022-11-01 17:25:39 -06:00
Tristan Sloughter 8bd410aaee
update tests to not rely on *_processor:set_exporter 2022-11-01 17:09:30 -06:00
Tristan Sloughter 58c6d5ad55
preload modules in elixir test so batch_processor runs start_link 2022-11-01 10:57:13 -06:00
Tristan Sloughter dd91b8e837
better support for multiple tracer providers
tracer providers should be able to be started by users and run
independently with their own procesors, and multiple of each
processor.

The SDK must register a simple_one_for_one that starts tracer
providers under the name otel_tracer_provider_sup. Then a
global tracer provider is started under the name
otel_tracer_server_global to be used when getting tracers
that aren't yet cached.
2022-10-31 17:55:31 -06:00
Tristan Sloughter 94a992ea00
Merge pull request #482 from tsloughter/bump-exporter-1.2.2
bump exporter to 1.2.2
2022-10-22 16:37:20 -06:00
Tristan Sloughter ae611d9118
bump exporter to 1.2.2 2022-10-21 05:35:11 -06:00
Tristan Sloughter 90f2a5bb64
Merge pull request #481 from tsloughter/grpc-channel-name
use self() for grpc channel name
2022-10-21 05:28:47 -06:00
Tristan Sloughter 25152473ed
use self() for grpc channel name
using ?MODULE limited us to a single grpcbox client channel. We
may want to not have a channel for each Signal (traces, meitrcs,
logs) if they are the same configuration, but for now this at
least allows each to export -- before only 1 could init their
exporter because it would conflict with the other.

Reuse of the channel is not as simple as using ?MODULE and if
it is already started use that channel because the endpoint may
be different. Not only that, the configuration to the endpoint
may be different, so a Channel name would have to be all the
distiguishing attributes of a Channel... Just easier to create
one for each Signal.
2022-10-20 17:43:56 -06:00
Tristan Sloughter f5084c1620
Merge pull request #480 from tsloughter/new-release
update changelog and docs script for new releases
2022-10-19 15:38:08 -06:00
Tristan Sloughter 333574833f
update changelog and docs script for new releases 2022-10-19 14:39:50 -06:00
Tristan Sloughter 998e29d04f
Merge pull request #479 from tsloughter/cleanup-old-experimental-api
Cleanup old experimental api
2022-10-19 11:49:57 -06:00
Tristan Sloughter a067e8db49
remove old elixir meteric api modules 2022-10-19 10:48:45 -06:00
Tristan Sloughter 4510813f48
remove unneeded VERSION file 2022-10-19 10:47:23 -06:00
Tristan Sloughter cfc7d98661
Merge pull request #478 from tsloughter/mv-otlp-metrics
Mv otlp metrics
2022-10-19 10:35:05 -06:00
Tristan Sloughter d4af43c17e
CHANGELOG: add notes for release of experimental apps 2022-10-18 15:55:16 -06:00
Tristan Sloughter afebcde5e6
add deps to experimental apps to prepare for publishing 2022-10-18 15:39:16 -06:00
Tristan Sloughter 864cad2954
fix up dependencies of experimental SDK app 2022-10-17 17:48:25 -06:00
Tristan Sloughter 92f306f346
move otlp metrics and logs to experimental 2022-10-17 17:45:43 -06:00
Tristan Sloughter 09b1e59d71
Merge pull request #477 from tsloughter/fix-exporter-stable
Fix exporter stable
2022-10-12 10:22:22 -06:00
Tristan Sloughter 080e6a3c9a
Merge branch 'main' into fix-exporter-stable 2022-10-11 15:30:28 -06:00
Tristan Sloughter e44e11f42a
add EXPERIMENTAL flag to dialyzer profile for github actions 2022-10-11 15:29:20 -06:00
Tristan Sloughter 56792ad313
Merge pull request #475 from tsloughter/delta-explicit-histogram
add delta support for explicit histogram
2022-10-11 15:24:52 -06:00
Tristan Sloughter 66b597675b
Merge branch 'main' into delta-explicit-histogram 2022-10-11 15:19:17 -06:00
Tristan Sloughter d59fcba9ab
Merge pull request #474 from tsloughter/gradualizer-2
phase 2 of gradualization
2022-10-11 15:17:17 -06:00
Tristan Sloughter 5af5930cdb
ignore opentelemetry_exporter xref errors for now 2022-10-07 15:12:41 -06:00
Tristan Sloughter 040be048b7
wrap otlp_metrics in an experimental option 2022-10-06 10:29:51 -06:00
Tristan Sloughter ce64f3b626
remove unneeded otel_metrics.hrl from opentelemetry_exporter module 2022-10-06 05:49:50 -06:00
Tristan Sloughter 866f659649
add delta support for explicit histogram 2022-10-05 16:19:59 -06:00
Tristan Sloughter 8e74efc14b
copy gradualizer.hrl to api include for use by other apps 2022-10-05 12:43:41 -06:00
Tristan Sloughter 5fad7afa6e
make assert_to_binary error if binary conversion fails 2022-10-05 11:03:35 -06:00
Tristan Sloughter 12f69c59c9
Update apps/opentelemetry_experimental/include/otel_metrics.hrl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-10-05 09:57:10 -06:00
Tristan Sloughter 95df2d8bb6
add ignore_xref attributes for gradualizer functions 2022-10-05 05:40:32 -06:00
Tristan Sloughter 470fda8b71
gradualizer phase 3 2022-10-05 05:40:32 -06:00
Tristan Sloughter 4cd11a6a60
baggage: add set_to that takes an explicit context to simplify types 2022-10-04 15:34:33 -06:00
Tristan Sloughter 77c637137e
gradualizer pass phase 2 2022-10-04 15:34:33 -06:00
Tristan Sloughter 3ece99cbe5
Merge pull request #472 from tsloughter/mv-metrics-hrl
move otel_metrics.hrl to include since its used by opentelemetry_exporter
2022-10-03 09:50:02 -06:00
Tristan Sloughter abacf9e4cd
Merge branch 'main' into mv-metrics-hrl 2022-10-02 05:24:03 -06:00
Tristan Sloughter 05fdd7d51e
move otel_metrics.hrl to include since its used by opentelemetry_exporter 2022-10-02 05:21:01 -06:00
Tristan Sloughter bd9d1f8d31
Merge pull request #470 from tsloughter/flush-shutdown
Flush shutdown
2022-10-01 16:42:25 -06:00
Tristan Sloughter ae70886cd4
Merge branch 'main' into flush-shutdown 2022-10-01 05:12:44 -06:00
Tristan Sloughter 8a5b2bfc7a
Merge pull request #471 from tsloughter/gradualizer
first pass at gradualizer cleanup
2022-10-01 04:39:55 -06:00
Tristan Sloughter 504b8549a7
set default tracer to noop after everything is shutdown 2022-09-30 16:19:49 -06:00
Tristan Sloughter 1ce49b2f0d
first pass at gradualizer cleanup 2022-09-30 16:06:17 -06:00
Tristan Sloughter b652275977
improve handling of shutdown by catching ets exceptions 2022-09-30 12:58:42 -06:00
Tristan Sloughter 31296e966f
Merge pull request #468 from tsloughter/log-sdk
Logging Handler
2022-09-29 17:05:42 -06:00
Tristan Sloughter 441ce7118a
batch_processor: flush batch table in terminate callback 2022-09-29 13:11:15 -06:00
Tristan Sloughter 5f3ac54196
remove SDK prep_stop noop tracer
Setting the default tracer to a noop in prep_stop wasn't only
wrong but also didn't really do anything since the tracer is
copied and not referenced, so existing tracers would remain
as is after setting the default to a noop.

But it is also wrong since we don't want to stop accepting traces
at any point and should try to create and export as many of
a users traces as we can before shutdown is complete.
2022-09-29 13:10:02 -06:00
Tristan Sloughter 8155c59c04
try to get common test failures into the github actions checks 2022-09-28 16:26:54 -06:00
Tristan Sloughter d11a693fb3
attempt conversion to binary string to check if var is unicode string 2022-09-28 16:11:59 -06:00
Tristan Sloughter cea8058554
proto encoding: properly check if binary/list is unicode string 2022-09-27 12:07:10 -06:00
Tristan Sloughter 0044259f1e
xref: ignore generated logs protobuf module 2022-09-26 05:23:09 -06:00
Tristan Sloughter a88e52e561
send report logs as structured data 2022-09-24 15:31:37 -06:00
Tristan Sloughter c37fed2f08
bump junit report github action 2022-09-24 15:07:46 -06:00
Tristan Sloughter b167ac096b
add note in batch processor 2022-09-23 17:36:44 -06:00
Tristan Sloughter d312c0b8b1
add logger handler which acts as LoggerProvider/Logger
This is a very simple version of what is needed to support the
logging spec and is in part duplicating code from the batch
span processor.

It has no overload protection and this will wait until we know
what is planned for log sampling in the spec as it will overlap.
2022-09-23 17:19:05 -06:00
Tristan Sloughter 446313a1a0
Merge pull request #456 from tsloughter/metrics-exporting
OTLP Metrics exporting
2022-09-21 06:19:03 -06:00
Tristan Sloughter 66b9f3c00f
only test metrics export once in grpc group 2022-09-21 06:15:35 -06:00
Tristan Sloughter 5c8c1f32e0
bump collector version 2022-09-20 10:06:40 -06:00
Tristan Sloughter d6e9015270
resolve dialyzer caught errors 2022-09-16 15:09:59 -06:00
Tristan Sloughter ef4f32d0c7
bump grpcbox and chatterbox versions at top level 2022-09-16 13:20:49 -06:00
Tristan Sloughter 589b4d36ec
add scope function to meter 2022-09-16 12:58:32 -06:00
Tristan Sloughter baaf13eaa9
test explicit bounds histogram exporting 2022-09-15 12:49:08 -06:00
Tristan Sloughter 2f004d2275
exporter: breakout trace and metric specific code to own modules 2022-09-15 12:49:08 -06:00
Tristan Sloughter 187dbec14e
add gauge to metrics export test 2022-09-15 12:49:08 -06:00
Tristan Sloughter 68115eb373
first successful metrics export to collector 2022-09-15 12:49:08 -06:00
Tristan Sloughter fa5355bdc0
test metrics encoding to proto 2022-09-15 12:49:01 -06:00
Tristan Sloughter 071f7cb80c
add scope to metrics table 2022-09-15 12:48:21 -06:00
Tristan Sloughter d791c5b8fd
Merge pull request #420 from andrewhr/fix-otlp-protocol-expected-values
Fix OTLP Protocol allowed values
2022-09-14 16:24:51 -06:00
Tristan Sloughter 418b911302
Merge branch 'main' into fix-otlp-protocol-expected-values 2022-09-14 15:02:54 -06:00
Tristan Sloughter 6b584df117
Merge pull request #460 from tsloughter/elixir-1.14
CI: add elixir 1.14 and remove 1.12
2022-09-14 15:02:42 -06:00
Tristan Sloughter f8a5863eba
CI: add elixir 1.14 and remove 1.12 2022-09-14 13:49:35 -06:00
Tristan Sloughter 48c1c4f175
Merge branch 'main' into fix-otlp-protocol-expected-values 2022-09-14 13:42:30 -06:00
Tristan Sloughter 5043d3807f
Merge pull request #457 from tsloughter/rm-telemetry-library
replace telemetry_library record with library info as resource attributes
2022-09-14 13:22:27 -06:00
Andrew Rosa 58755595f7
Fix OTLP Protocol allowed values
As the [specification describes][1], there are 3 possible values for ENV vars
that set the OTLP protocol used by OTLP exporter:
- grpc
- http/protobuf
- http/json

The SDK implementation leans on `list_to_existing_atom` function, so our
expected values are in fact `http_protobuf` instead of `http/protobuf`
for example.

This is confusing for ones following the generic documentation, and also
may become a problem in polyglot environments: let's say, I share the
same ENV setup for a Java and Erlang application.

The fix here account for the current atom values, and strings with the
same snake_case format for backwards compatibility. But also accept the
standard approach.

The fix includes `http/json` as possible transform, but the exporter
will still fails as that isn't supported by our impl.

[1]: 82707fd9f7/specification/protocol/exporter.md (specify-protocol)
2022-09-14 11:26:53 -03:00
Tristan Sloughter 7fa89ba4f6
replace telemetry_library record with library info as resource attributes 2022-09-09 15:49:40 -06:00
Tristan Sloughter c5c785c045
Merge pull request #454 from tsloughter/bump-otlp-1.2.0
bump otlp exporter to 1.2.0
2022-09-08 13:38:08 -06:00
Tristan Sloughter 7146b0a15c
bump otlp exporter to 1.2.0 2022-09-08 10:17:51 -06:00
Tristan Sloughter 4f55da324d
Merge pull request #451 from tsloughter/export-scope
Fix InstrumentationScope in OTLP protos
2022-09-08 10:14:53 -06:00
Tristan Sloughter 9908d61bd6
Merge branch 'main' into export-scope 2022-09-08 10:04:46 -06:00
Tristan Sloughter 632acb1286
Merge pull request #453 from kenichi/pr_442_changelog
add exporter updates in #442 to changelog
2022-09-08 04:59:23 -06:00
Kenichi Nakamura ba54ca48d0 add exporter updates in #442 to changelog 2022-09-07 21:23:03 -07:00
Tristan Sloughter 46751c033c
add exporter scope fix to changelog 2022-09-07 16:31:53 -06:00
Tristan Sloughter 950066e22f
fix InstrumentationScope in OTLP protobuf encoding to be `scope` 2022-09-07 16:29:52 -06:00
Tristan Sloughter ef38b7d55b
add logging exporter to test collector 2022-09-07 16:28:47 -06:00
Tristan Sloughter ca54f257c5
bump otlp proto version to 0.19.0 2022-09-07 16:28:33 -06:00
Tristan Sloughter 323b3ff411
Merge pull request #442 from kenichi/app_env_ssl_options
Exporter app env SSL options
2022-09-06 11:30:09 -06:00
Tristan Sloughter 490f61859b
Merge branch 'main' into app_env_ssl_options 2022-09-06 11:06:46 -06:00
Tristan Sloughter 7b3cb40724
Merge pull request #445 from tsloughter/result-observer
Use return of callback for measurements of observable instruments
2022-09-06 10:43:40 -06:00
Tristan Sloughter 5246ad834b
add observation type for return of observable callback 2022-09-05 12:13:38 -06:00
Tristan Sloughter 2b6cdedce2
make callback ets table a bag so funs can be reused by multiple instruments 2022-09-02 14:59:12 -06:00
Tristan Sloughter d6034a5e46
remove unneeded sync_record function from meter 2022-09-02 14:59:12 -06:00
Tristan Sloughter bc912833b6
fix instrument callback type spec 2022-09-02 14:59:12 -06:00
Tristan Sloughter d468f8603d
add callback args to observable callback 2022-09-02 14:59:11 -06:00
Tristan Sloughter 840af9ba8a
use return of recorded value from observation functions for aggregation 2022-09-02 14:59:11 -06:00
Tristan Sloughter ab80409bd8
add locals_not_used xref check 2022-09-02 14:59:11 -06:00
Tristan Sloughter e23fc6af22
support multi-instrment callback observers 2022-09-02 14:59:11 -06:00
Tristan Sloughter 879df93694
add support for ObservableGauge 2022-09-02 14:59:11 -06:00
Tristan Sloughter c3980f7890
add support for ObservableUpDownCounter 2022-09-02 14:59:11 -06:00
Tristan Sloughter 15aa0210bf
update observablecounter debug log instrument name 2022-09-02 14:59:11 -06:00
Tristan Sloughter c34270bab9
add blocking record function for use in observable instruments 2022-09-02 14:59:10 -06:00
Tristan Sloughter 3030799d80
use otel_exporter interface for metrics exporting 2022-09-02 14:59:10 -06:00
Tristan Sloughter b79fc76537
make net_kernel:start failure easier to reader in ct output 2022-09-02 14:59:10 -06:00
Tristan Sloughter 503f3be477
observable_counter for single instrument callback
An observable_counter takes a callback as an argument. The callback
receives the Instrument to take measurements with as an argument.
2022-09-02 14:59:10 -06:00
Tristan Sloughter d5908572ed
Merge pull request #450 from tsloughter/cut-1.1.1
bump otlp exporter to 1.1.1 and zipkin to 1.1.0
2022-09-02 12:50:08 -06:00
Tristan Sloughter 126e2070b7
bump versions in docs.sh for generating latest docs 2022-09-02 12:03:06 -06:00
Tristan Sloughter edac2aa9d9
bump otlp exporter to 1.1.1 and zipkin to 1.1.0 2022-09-02 12:00:47 -06:00
Tristan Sloughter a7ea2a92c1
Merge pull request #448 from tsloughter/fix-zipkin
update zipkin exporter for new export api of export/4
2022-09-02 11:56:18 -06:00
Tristan Sloughter 7223f85e6c
Merge branch 'main' into fix-zipkin 2022-09-02 11:52:19 -06:00
Tristan Sloughter 93dcc20c9b
Merge pull request #449 from tsloughter/fix-1.1-deps
bump required api/sdk to 1.1 for new releases
2022-09-02 11:51:30 -06:00
Tristan Sloughter 290f05978a
update zipkin exporter for new export api of export/4 2022-09-02 10:41:13 -06:00
Tristan Sloughter 505e7fb1dc
bump required api/sdk to 1.1 for new releases 2022-09-02 10:38:25 -06:00
Tristan Sloughter aafd1f34e9
Merge pull request #444 from tsloughter/bump-1.1.0
bump versions of api, sdk and exporter to 1.1.0
2022-08-31 11:04:51 -06:00
Tristan Sloughter 2fcedc9cde
bump versions of api, sdk and exporter to 1.1.0 2022-08-31 05:11:35 -06:00
Kenichi Nakamura 3a21c67354 update config examples 2022-08-29 10:32:22 -07:00
Kenichi Nakamura 285486da5d reduce uri parse error log to warning, add example config 2022-08-26 14:33:52 -07:00
Kenichi Nakamura 5841460277 fix: handle app env endpoint uri value with extra quotes 2022-08-26 09:47:15 -07:00
Fred Hebert bd96c1b1d1
Merge pull request #439 from luizdamim/main
Improve Sampler documentation
2022-08-26 08:06:52 -04:00
Kenichi Nakamura 82b75317c3 fix: use top-level ssl_options set in app env 2022-08-25 19:28:06 -07:00
Luiz Damim 86e079a345 Improve Sampler documentation 2022-08-25 11:19:51 +02:00
Tristan Sloughter 28facc303d
Merge pull request #435 from tsloughter/otlp-metrics
add type arg to export and metrics protos
2022-08-23 06:20:04 -06:00
Tristan Sloughter 2cc73a6d5a
add metrics protos for exporting metrics with otlp 2022-08-23 05:32:37 -06:00
Tristan Sloughter b241b7e7da
add an argument to export callback to say if it is traces or metrics 2022-08-19 05:18:53 -06:00
Tristan Sloughter c47da70acd
Merge pull request #434 from tsloughter/no-run-tls-cert-check
only run tls_certificate_check if ssl options are needed
2022-08-19 05:14:51 -06:00
Tristan Sloughter a8b50457a7
Merge branch 'main' into no-run-tls-cert-check 2022-08-19 05:10:37 -06:00
Tristan Sloughter 4200a9386c
Merge pull request #432 from tsloughter/instance-tests
make resource instance name tests run
2022-08-19 05:10:19 -06:00
Tristan Sloughter fc56aff390
only run tls_certificate_check if ssl options are needed 2022-08-18 13:23:29 -06:00
Tristan Sloughter c1f433aea0
skip node name tests in CI 2022-08-18 12:51:58 -06:00
Tristan Sloughter 1e68299220
use shortnames in resource detector test 2022-08-18 12:51:58 -06:00
Tristan Sloughter 36d04ff310
make resource instance name tests run 2022-08-18 12:51:58 -06:00
Tristan Sloughter b5840d2338
Merge pull request #431 from tsloughter/reader-sup
move readers under metrics supervisor and require registered reader
2022-08-18 12:09:40 -06:00
Tristan Sloughter 19cbded73f
Merge branch 'main' into reader-sup 2022-08-18 12:07:33 -06:00
Tristan Sloughter 0315a48f1f
add ct:pal print out to experimental UNTIL macro 2022-08-18 10:42:35 -06:00
Tristan Sloughter 19b9d4058d
Merge pull request #410 from btkostner/patch-1
add record_exception/1 to OpenTelemetry.Tracer
2022-08-17 15:26:08 -06:00
Tristan Sloughter 3546112110
Merge branch 'main' into patch-1 2022-08-17 14:47:42 -06:00
Tristan Sloughter 82cd16d3a7
Merge pull request #409 from fcevado/service-instance-id-default-value
Add service.instance.id resource default value
2022-08-17 14:28:03 -06:00
Tristan Sloughter 59513640a9
Merge branch 'main' into service-instance-id-default-value 2022-08-17 14:17:22 -06:00
Tristan Sloughter a44d639e40
test macros: use try/catch in test macro UNTIL 2022-08-17 10:03:13 -06:00
Tristan Sloughter dcacd3d14f
move readers under metrics supervisor and require registered reader
This patch moves readers under a readers supervisor instead of being
started from the metrics server. Readers must be declared in config
and provided with a unique atom name that is used for registration
of the process. This name is also used to create named ets tables
to store the view aggregation mappings and the metrics.

Use of named ets tables and registered processes means the pid and
tids don't need to be tracked but a future update may find it
better to remove the need for names.
2022-08-17 09:54:21 -06:00
Tristan Sloughter 2a700f868b
Merge pull request #412 from tsloughter/stable-metrics-sdk
Stable metrics sdk
2022-08-10 18:18:20 -06:00
Tristan Sloughter 352cfad540
use rebar3 3.17.0 in elixir tests 2022-08-10 11:41:31 -06:00
Tristan Sloughter 6b8885b66a
only run dialyzer on latest supported OTP 2022-08-10 10:35:48 -06:00
Tristan Sloughter 229707772a
bump otp 23 version in CI to 23.3.4.16 2022-08-10 10:35:48 -06:00
Tristan Sloughter edaa404a7d
mix install locally available rebar3 2022-08-10 10:35:48 -06:00
Tristan Sloughter 255823f6fe
clear cache in failing mix cover step 2022-08-09 17:18:30 -06:00
Tristan Sloughter 0ba607d1b2
force update of rebar3 by mix 2022-08-09 17:12:22 -06:00
Tristan Sloughter a9093da849
remove unneeded config in github actions 2022-08-09 17:10:01 -06:00
Tristan Sloughter 8087b9b4aa
bump elixir to 1.12.3 in CI 2022-08-09 17:10:01 -06:00
Tristan Sloughter 4cf7e0370f
fix reader configuration type spec 2022-08-09 17:10:01 -06:00
Tristan Sloughter c922c01304
bump rebar3 to 3.19.0 in CI 2022-08-09 17:10:01 -06:00
Tristan Sloughter d0820fe81d
use -2^63 for the initial min value in explicit histogram 2022-08-09 17:10:01 -06:00
Tristan Sloughter d6f419d168
add note about improving explicit histogram aggregate function 2022-08-09 17:10:01 -06:00
Tristan Sloughter 3632353abb
improve type specs in metrics code 2022-08-09 17:10:01 -06:00
Tristan Sloughter d0ce967458
metrics pid exporter: tag wrapping metric message, default: otel_metric 2022-08-09 17:10:00 -06:00
Tristan Sloughter 4ff6d3342b
pr cleanup: use async timer cancel and add value_or function 2022-08-09 17:10:00 -06:00
Tristan Sloughter 4459ed3f27
add logging on bad instrument use 2022-08-09 17:10:00 -06:00
Tristan Sloughter 534ff0ace6
Update apps/opentelemetry_experimental/src/otel_metric_reader.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-08-09 17:10:00 -06:00
Tristan Sloughter b4c42653db
export get_meter/4 in meter provider 2022-08-09 17:10:00 -06:00
Tristan Sloughter f37045b587
remove unneeded TODO about removed view_aggregation reader_pid 2022-08-09 17:10:00 -06:00
Tristan Sloughter 4ff9629f7e
support configurable metric reader export interval 2022-08-09 17:10:00 -06:00
Tristan Sloughter 23f06ec72a
fix up dialyzer warnings 2022-08-09 17:09:59 -06:00
Tristan Sloughter ce92db660b
use agg defaults for instrument with no matching view 2022-08-09 17:09:59 -06:00
Tristan Sloughter cb0f9bccfd
add this PR to the changelog 2022-08-09 17:09:59 -06:00
Tristan Sloughter 5c19956a00
bump codecov action to v3 2022-08-09 17:09:59 -06:00
Tristan Sloughter 2ead59e172
add lastvalue checkpointing 2022-08-09 17:09:59 -06:00
Tristan Sloughter 974e6eaebd
add histogram checkpointing 2022-08-09 17:09:59 -06:00
Tristan Sloughter 7860e029ec
add otp 25 and remove 22 from CI 2022-08-09 17:09:59 -06:00
Tristan Sloughter b22bbdb334
remove reader_pid from view_aggregation since separate tables are used 2022-08-09 17:09:58 -06:00
Tristan Sloughter 7b0a28cea5
use checkpoints of metrics for collection
In order to collect the current value of a metric, and reset it in
the case of a delta temporality, the reader process first must
checkpoint each metric. Checkpointing copies the current value to
a checkpoint field of the aggregation record and resets the value
and start time if needed. Then the checkpoint field is used to get
the metric value when collecting.

This is the easiest method to collect metrics without potentially
losing measurements during a reset that works across all types of
aggregations. There may be optimizations that can be done per
aggregation in the future.

The aggregation checkpoint function is called for each metric
individually, but this should likely change to have it so the
reader only has to call checkpoint for an aggregation and it
runs against all metrics in the table.
2022-08-09 17:09:58 -06:00
Tristan Sloughter a17e70aa89
require provider name/pid in arguments to otel_meter_server functoin calls 2022-08-09 17:09:58 -06:00
Tristan Sloughter 19e39efa72
update metrics console exporter to support new reader metrics datapoints 2022-08-09 17:09:58 -06:00
Tristan Sloughter f920cd3945
ignore metric values of differnet type than the instrument 2022-08-09 17:09:58 -06:00
Tristan Sloughter fc6484911e
rm create_ prefix to make clear it has no side effect to get instrument 2022-08-09 17:09:58 -06:00
Tristan Sloughter 7ad0cbb6ca
use previous instrument matches to find aggregations for measurements 2022-08-09 17:09:57 -06:00
Tristan Sloughter 696289d666
add test for per-reader default aggregations 2022-08-09 17:09:57 -06:00
Tristan Sloughter e673217c74
metrics: use per-reader ETS tables 2022-08-09 17:09:57 -06:00
Tristan Sloughter 3b9b4b9e2c
support options to view aggregations 2022-08-09 17:09:57 -06:00
Tristan Sloughter 0a8c95fa58
move to single active_metric record for value in ets table 2022-08-09 17:09:57 -06:00
Tristan Sloughter 0362ea578b
use per-reader metric storage 2022-08-09 17:09:57 -06:00
Tristan Sloughter 1a92e31813
move view aggregations to only ets table 2022-08-09 17:09:57 -06:00
Tristan Sloughter 97a7926cac
inefficient explicit bounds histogram 2022-08-09 17:09:56 -06:00
Tristan Sloughter c1a053fbbd
add gauge support 2022-08-09 17:09:56 -06:00
Tristan Sloughter d99df9c469
initial metrics API rewrite for stable spec 2022-08-09 17:09:56 -06:00
Tristan Sloughter f2f172ee86
start on new metrics API 2022-08-09 17:09:56 -06:00
Tristan Sloughter 6990ff30ff
Merge pull request #414 from tsloughter/rm-resource-tracer
remove resource field from tracer record
2022-08-07 10:32:40 -06:00
Tristan Sloughter b2f1f56dbe
Merge branch 'main' into rm-resource-tracer 2022-08-07 10:23:21 -06:00
Blake Kostner 779856b2de
Merge branch 'main' into patch-1 2022-07-28 18:12:12 -06:00
Fred Hebert a0980f7160
Merge pull request #415 from sax/docs-traces-exporter-none
Add traces_exporter: :none to documentation
2022-07-25 13:24:42 -04:00
Eric Saxby a4ce95a957 Update description of traces_exporter: :none 2022-07-25 09:05:42 -07:00
Eric Saxby 4d05ebf0f1 Add traces_exporter: :none to documentation 2022-07-23 10:35:33 -07:00
Tristan Sloughter f4ec1b29ee
remove resource field from tracer record
The Resource is created on startup and the same for the entire
node. There is no need to carry it in the tracer record since
the processor that exports spans gets the Resource from the
tracer provider for attaching to the spans it exports.
2022-07-23 06:14:33 -06:00
Tristan Sloughter 6b098f5c31
Merge pull request #413 from tsloughter/drop-spans-no-exporter
drop spans immediately if no exporter is configured
2022-07-22 14:58:06 -06:00
Tristan Sloughter 92fc0c0aaa
Merge branch 'main' into drop-spans-no-exporter 2022-07-21 11:58:48 -06:00
Tristan Sloughter 744e4b4efe
Merge pull request #400 from chad-g-adams/documentation-for-samplers
add documentation about samplers
2022-07-21 11:58:38 -06:00
Tristan Sloughter bbf646632b
Merge branch 'main' into documentation-for-samplers 2022-07-21 11:41:29 -06:00
Tristan Sloughter 3a67359ff2
add test that spans are not added to export table with no exporter 2022-07-21 07:53:43 -06:00
Tristan Sloughter 10c90204a8
drop spans immediately if no exporter is configured 2022-07-21 06:57:14 -06:00
Tristan Sloughter 76781ecc28
Merge pull request #399 from qdentity/docs-tls_certificate_check
Document usage of opentelemetry_exporter in Elixir apps
2022-07-18 06:01:03 -06:00
dvic da81eb0b60
Better document usage of opentelemetry_exporter in Elixir apps 2022-07-18 07:56:38 +02:00
Blake Kostner fba617ca8f add record_exception/4 and record_exception/5 to otel_tracer.hrl 2022-07-05 11:51:51 -06:00
Blake Kostner 981d85345c happy formatter happy life 2022-07-01 12:11:25 -06:00
Blake Kostner 01d41249c9
compress function heads 2022-07-01 11:46:09 -06:00
Blake Kostner 401724bd73
add record_exception/1 to OpenTelemetry.Tracer 2022-07-01 11:45:08 -06:00
cevado d6dad5f803
Rename required_attributes to default_resource_attributes 2022-06-30 20:48:58 -03:00
cevado f1a9b40c86
Use random id when node name has localhost. 2022-06-30 20:48:58 -03:00
cevado 83d2e883a7
Add more tests for service.instance.id to increase coverage 2022-06-30 20:48:58 -03:00
cevado 760086dbd4
Add service.instance.id resource default value 2022-06-30 20:48:52 -03:00
Tristan Sloughter 5479712c89
Merge pull request #394 from tsloughter/log-md
add trace ctx to logger metadata when attached to pdict context
2022-06-30 14:26:59 -06:00
Tristan Sloughter a6b8976920
logger metadata: use a flat set of key/values for span ctx
since Elixir's Logger formatter does not support nested keys for
metadata, like Erlang logger formatter does, this patch changes
the metadata from #{otel_span_ctx => #{...}} to remove the wrapping
`otel_span_ctx`. This also meant changing the example logger format
template to have to check for existance of each key individually.
2022-06-30 12:20:44 -06:00
Tristan Sloughter 07418404e0
add usage example of logger metadata 2022-06-29 17:23:19 -06:00
Tristan Sloughter f5abede28e
add trace ctx to logger metadata when attached to pdict context 2022-06-29 17:23:13 -06:00
chad-g-adams c44344f538 add examples for 3 functions that are part of the behaviour 2022-06-19 12:31:27 -04:00
Tristan Sloughter 2964d0b1a5
Merge pull request #405 from tsloughter/instrumentation-scope
replace InstrumentationLibrary with InstrumentationScope
2022-06-12 06:00:18 -06:00
Tristan Sloughter 7dadcc23a0
add note to changelog about insturmentation_library record usage 2022-06-11 12:55:39 -06:00
Tristan Sloughter 8054cdd388
update comment on instrumentation_scope record 2022-06-11 12:52:14 -06:00
Tristan Sloughter 657d8ffff8
replace InstrumentationLibrary with InstrumentationScope
Spec change can be found in PR:
 https://github.com/open-telemetry/opentelemetry-specification/pull/2276
2022-06-11 12:50:27 -06:00
Tristan Sloughter ccbe7f182e
Merge pull request #408 from ananthakumaran/custom-propagator
Allow custom text propagator to be configured via application env
2022-06-11 12:38:28 -06:00
Anantha Kumaran a4b4d90da8 allow custom propagator 2022-06-11 18:26:15 +05:30
chad-g-adams 077f1d087e add documentation about samplers 2022-05-27 07:20:31 -04:00
Tristan Sloughter 94d385d494
Merge pull request #398 from tsloughter/sdk-bump-1.0.5
bump SDK to 1.0.5
2022-05-20 19:00:57 -06:00
Tristan Sloughter 3fbe7a5e1a
bump SDK to 1.0.5 2022-05-20 18:00:08 -06:00
Tristan Sloughter 58cfd2225c
Merge pull request #397 from tsloughter/processor-config-again
span processor config: don't override user settings with defaults
2022-05-20 12:17:33 -06:00
Tristan Sloughter 8998bae541
span processor config: don't override user settings with defaults 2022-05-19 16:06:16 -06:00
Tristan Sloughter 95e6763dd3
Merge pull request #395 from tsloughter/sdk-bump-1.0.4
bump SDK to 1.0.4
2022-05-14 04:41:23 -06:00
Tristan Sloughter 7bd6af938b
bump SDK to 1.0.4 2022-05-13 17:19:31 -06:00
Tristan Sloughter 41552e307a
Merge pull request #393 from tsloughter/none-tracer
fix use of traces_exporter app env var for setting the exporter
2022-05-13 05:24:37 -06:00
Tristan Sloughter 9f222df312
fix use of traces_exporter app env var for setting the exporter
The atom `none` is now used instead of `undefined` for telling the
exporter to do nothing. This was done because `undefined` is used
in `otel_configuration` to signal that a variable is not set and
to not override it in the processor's config. That lead to the
`traces_exporter` value not being used if it was set to `none` or
`undefined` by the user.
2022-05-12 16:04:26 -06:00
Tristan Sloughter e18d84523b
Merge pull request #390 from tsloughter/ts/exporter-1.0.4
bump otlp exporter version to 1.0.4
2022-05-10 15:57:10 -06:00
Tristan Sloughter 77ab49f709
bump otlp exporter version to 1.0.4 2022-05-06 16:03:47 -06:00
Tristan Sloughter 6cd9491da9
Merge pull request #389 from tsloughter/ts/https-port
fix bug where port 443 is used even for https
2022-05-06 16:00:57 -06:00
Tristan Sloughter 05d58f935f
fix bug where port 443 is used even for https
scheme_port/1 was expecting an atom when it was getting a string.
It would fall back to port 80 and this would result in failing to
connect to https endpoints unless they had an explicit port given
in the url.
2022-05-06 05:54:12 -06:00
Tristan Sloughter f1cadef5a3
Merge pull request #388 from tsloughter/bump-vsn-1.0.3
update changelog and vsns for api/sdk/exporter 1.0.3
2022-04-29 12:16:14 -06:00
Tristan Sloughter d438061c06
update changelog and vsns for api/sdk/exporter 1.0.3 2022-04-28 14:32:05 -06:00
Tristan Sloughter 2e967965e4
Merge pull request #386 from tsloughter/exporter-key
fix examples to use traces_exporter as config key
2022-04-28 14:24:49 -06:00
Tristan Sloughter 3f20282dbf
Merge branch 'main' into exporter-key 2022-04-28 14:24:36 -06:00
Tristan Sloughter 8a36320b74
Merge pull request #387 from tsloughter/exporter-start-deps
remove opentelemetry from exporter applications list
2022-04-28 14:23:53 -06:00
Tristan Sloughter fb81761c7a
remove opentelemetry from exporter applications list
The exporter does not depend on the opentelemetry application to
be started before it, so there is no need for it to be in the
list of applications in .app.src since that is for ensuring
an application has been started in a release before it.
2022-04-28 13:34:44 -06:00
Tristan Sloughter 04e74268bf
fix examples to use traces_exporter as config key 2022-04-27 12:41:45 -06:00
Bryan Naegele 0ea0431376
Merge pull request #383 from hkrutzer/docs_clarify_tracer_end_span
Clarify difference between Tracer and Span end_span docs
2022-04-27 10:27:07 -06:00
Hans Krutzer ccc9620546 Clarify difference between Tracer and Span end_span in docs 2022-04-27 10:22:04 -06:00
Tristan Sloughter 8b355ee37a
Merge pull request #384 from tsloughter/rm-select-replace
set_status: use update_element since select_replace doesn't use index
2022-04-27 05:56:56 -06:00
Tristan Sloughter 6cf7b36435
set_status: use update_element since select_replace doesn't use index 2022-04-27 05:53:54 -06:00
Tristan Sloughter f9996ded4d
Merge pull request #378 from tsloughter/default-endpoint-path
set default endpoint path to the default path for traces /v1/traces
2022-03-19 13:22:53 -06:00
Tristan Sloughter a207000ceb
set default endpoint path to the default path for traces /v1/traces 2022-03-18 16:32:13 -06:00
Tristan Sloughter 0ca30c88f4
Merge pull request #373 from calvin-kargo/fix_example_on_otel_propragator_text_map
Minor fix for example on otel_propragator_text_map example
2022-03-17 10:28:33 -06:00
Tristan Sloughter 0a02b4b323
Merge branch 'main' into fix_example_on_otel_propragator_text_map 2022-03-17 10:22:33 -06:00
Tristan Sloughter a550663161
Merge pull request #376 from tsloughter/binary-string-endpoint
otlp exporter: fix handling of binary string endpoint
2022-03-09 15:25:06 -07:00
Tristan Sloughter 20469a2e4a
update changelog for PR-376 fixing exporter otlp_endpoint usage 2022-03-09 14:52:49 -07:00
Tristan Sloughter c36627d169
otlp exporter: fix handling of binary string endpoint 2022-03-09 14:22:27 -07:00
Tristan Sloughter 03d924e36b
Merge pull request #374 from marpo60/patch-1
Update README.md
2022-03-04 12:52:26 -07:00
Marcelo Dominguez 0d15583f0b
Update README.md 2022-03-04 16:07:43 -03:00
calvinsadewa a26836310d Merge branch 'fix_example_on_otel_propragator_text_map' of github.com:calvin-kargo/opentelemetry-erlang into fix_example_on_otel_propragator_text_map 2022-03-01 18:04:30 +07:00
calvinsadewa 42cd975045 fix opentelemetry:get_text_map_injector on example 2022-03-01 18:04:05 +07:00
calvin-kargo fd48f7d04d
Merge branch 'main' into fix_example_on_otel_propragator_text_map 2022-03-01 17:55:52 +07:00
calvinsadewa b9e666f2ba Minor fix for example on otel_propragator_text_map example 2022-03-01 17:51:10 +07:00
Tristan Sloughter 28b383da8e
Merge pull request #372 from tsloughter/fix-http-port
fix http protobuf port in exporter readme
2022-02-25 12:52:59 -07:00
Tristan Sloughter 388c3e42a3
fix http protobuf port in exporter readme 2022-02-25 05:27:47 -07:00
Tristan Sloughter ff27752800
Merge pull request #369 from tsloughter/fix-readme-render
convert badges from markdown to html to work with github rendering
2022-02-24 17:56:13 -07:00
Tristan Sloughter f9c9dbebe4
convert badges from markdown to html to work with github rendering 2022-02-24 15:33:59 -07:00
Tristan Sloughter 69ece56019
Merge pull request #368 from tsloughter/codecov-badge
add codecov badge
2022-02-24 15:17:28 -07:00
Tristan Sloughter 262c61143b
add codecov badge 2022-02-24 14:29:56 -07:00
Tristan Sloughter 0e381d3978
Merge pull request #367 from tsloughter/pb-cover-exclude
ignore large proto generated files in coverage
2022-02-24 13:38:13 -07:00
Tristan Sloughter 38bc1e46e4
ignore large proto generated files in coverage 2022-02-24 12:31:55 -07:00
Tristan Sloughter 388b554928
Merge pull request #365 from tsloughter/doc-gen-sdk-exporter
fixup sdk and exporter doc generation
2022-02-24 12:31:35 -07:00
Tristan Sloughter fef7901ec9
fixup sdk and exporter doc generation 2022-02-23 17:06:41 -07:00
Tristan Sloughter 889a0e5f01
Merge pull request #364 from tsloughter/bump-1.0.2
Bump 1.0.2
2022-02-22 15:17:54 -07:00
Tristan Sloughter 338e4b2ed1
bump api, sdk and exporter to 1.0.2 and zipkin to 1.0.0 2022-02-22 14:21:27 -07:00
Tristan Sloughter f8965567c1
add zipkin docs generation 2022-02-22 14:21:01 -07:00
Tristan Sloughter 2574d64678
Merge pull request #362 from tsloughter/api-readme
Add docs for the tracing api macros to the readme
2022-02-22 11:42:44 -07:00
Tristan Sloughter 7e45530c3e
elixir sdk tests: no need to start exporter bc tests use pid exporter 2022-02-22 11:39:11 -07:00
Tristan Sloughter b85e739b98
add explainer about resetting context after with_span 2022-02-22 10:37:11 -07:00
Tristan Sloughter fd90b62657
add getting started link to top level readme 2022-02-21 14:49:41 -07:00
Tristan Sloughter 705133db61
use --no-start to fix tls_certificate_check warning in mix test 2022-02-21 14:49:41 -07:00
Tristan Sloughter 4035a43c18
elixir api: remove unused deps and mix.exs code 2022-02-21 14:49:41 -07:00
Tristan Sloughter a809e99572
Update apps/opentelemetry_api/README.md
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-02-21 14:40:18 -07:00
Tristan Sloughter a9e16f6080
update changelog with entry about span status fix 2022-02-17 15:21:04 -07:00
Tristan Sloughter 7fb6167e13
set_status: follow spec which defines precedence of values
If set_status has already been called and set to OK then another
set_status can not change the value after that. If it was set to
ERROR then it can only updated to OK.
2022-02-17 13:06:55 -07:00
Tristan Sloughter e3dbbe976c
Merge branch 'main' into api-readme 2022-02-17 10:25:53 -07:00
Tristan Sloughter 1a8b77c8be
api: support for just status code in set_status api 2022-02-16 19:49:12 -07:00
Tristan Sloughter f90f799ae6
api readme: make clear exceptions are not caught in with_span 2022-02-16 15:47:22 -07:00
Tristan Sloughter 01e49441d3
Merge pull request #363 from tsloughter/zipkin-spec
improvements to zipkin exporter
2022-02-16 14:16:57 -07:00
Tristan Sloughter 9d4facd304
zipkin: use empty string value if characters_to_binary fails 2022-02-16 10:46:08 -07:00
Tristan Sloughter f25f099949
ignore experimental apps from coverage 2022-02-16 07:03:39 -07:00
Tristan Sloughter 4f78d0f2b3
zipkin: convert otel status to tags 2022-02-16 06:17:02 -07:00
Tristan Sloughter 86041abdc7
fix zipkin attribute->tag encoding 2022-02-15 19:39:32 -07:00
Tristan Sloughter b1694036f3
exclude experimental apps from coverage 2022-02-15 18:09:36 -07:00
Tristan Sloughter 1aa86dfd0f
add API macro docs to the README 2022-02-15 18:09:36 -07:00
Tristan Sloughter ffadbbcca3
add set_status that takes a code and message 2022-02-15 18:09:32 -07:00
Tristan Sloughter feb17eabb8
Merge pull request #360 from tsloughter/readme-updates
Readme updates
2022-02-15 14:09:41 -07:00
Tristan Sloughter f1a9dafec9
Merge branch 'main' into readme-updates 2022-02-15 13:49:48 -07:00
Tristan Sloughter ea7649c988
Merge pull request #361 from jhonndabi/fix/readme-elixir-release-config-instructions
fix: readme elixir release config instructions
2022-02-15 13:49:13 -07:00
Jonadabe Nascimento c5830cc141 chore: remove unnecessary inclusion of app in release applications config 2022-02-15 15:18:11 -03:00
Jonadabe Nascimento 4fada8480b fix: readme elixir release config instructions 2022-02-15 14:03:20 -03:00
Tristan Sloughter f7f9f2a757
Update apps/opentelemetry/README.md
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-02-12 06:29:09 -07:00
Tristan Sloughter 0c242086bd
update docs.config and move top level one to SDK 2022-02-11 17:15:54 -07:00
Tristan Sloughter c3ae4eaba7
update exporter README to document otlp_ config options 2022-02-11 16:59:11 -07:00
Tristan Sloughter 128d95461e
add SDK README 2022-02-11 16:58:44 -07:00
Tristan Sloughter d36395f747
remove no longer needed doc configuration 2022-02-10 14:45:04 -07:00
Tristan Sloughter 014bf935ab
update changelog for new configuration change 2022-02-10 13:19:41 -07:00
Tristan Sloughter 39fad9800e
make the readme the start page of API hex docs 2022-02-10 13:19:41 -07:00
Tristan Sloughter 2cf4fec4b4
Merge pull request #359 from erszcz/build-erlang-elixir-api-docs
Build Erlang and Elixir docs for opentelemetry_api
2022-02-10 13:11:26 -07:00
Tristan Sloughter 0f1c08c1bc
Merge branch 'main' into build-erlang-elixir-api-docs 2022-02-10 09:16:27 -07:00
Tristan Sloughter 600257af50
Merge pull request #352 from maciej-szlosarczyk/update-exporter-documentation
Update documentation on configuring the exporter via a map
2022-02-10 09:16:05 -07:00
Tristan Sloughter b6d5f3ea16
Merge branch 'main' into update-exporter-documentation 2022-02-10 09:12:48 -07:00
Radek Szymczyszyn 218cfdd9a6 Build Erlang and Elixir docs for opentelemetry_api 2022-02-10 14:09:59 +01:00
Tristan Sloughter a25274355f
Merge pull request #357 from tsloughter/simple-config
simpler and flat configuration options
2022-02-09 17:36:20 -07:00
Tristan Sloughter 764cb2ae1c
configuration: support top level batch/simple processor config 2022-02-09 17:32:02 -07:00
Tristan Sloughter e888665a07
remove opentelemetry.app defaults, handled in otel_configuration 2022-02-07 17:26:26 -07:00
Tristan Sloughter 7f83bea9fd
configuration: support atom name otlp for exporter 2022-02-07 17:22:41 -07:00
Tristan Sloughter 90c1755e4b
exporter: use protocol specific defaults 2022-02-07 15:11:25 -07:00
Maciej Szlosarczyk dc94e4b4d1
Move endpoint documentation to the module 2022-02-07 16:27:01 +02:00
Maciej Szlosarczyk 06fbdc2eb8
Correct information about multiple grpc endpoints 2022-02-04 13:16:02 +02:00
Maciej Szlosarczyk 9f412ed25c
Update documentation on configuring the exporter via a map
- Add info on compression
- Describe all 3 ways in which an endpoint can be configured
- Add information on default port
- Add the gotcha about using only the first endpoint
- Fix a minor typo
2022-02-04 13:16:02 +02:00
Tristan Sloughter adc2a4df26
Merge pull request #356 from tsloughter/bump-1.0.1
bump versions of api, sdk and exporter to 1.0.1
2022-02-03 17:20:19 -07:00
Tristan Sloughter 4703768325
bump versions of api, sdk and exporter to 1.0.1 2022-02-03 16:36:59 -07:00
Tristan Sloughter 3b4f3a3079
Merge pull request #355 from tsloughter/composite-report-cb
add report_cb to format log messages in composite propagator
2022-02-03 16:16:53 -07:00
Tristan Sloughter c88bb5159e
add report_cb to format log messages in composite propagator 2022-02-03 16:12:18 -07:00
Tristan Sloughter e518fcc9d3
Merge pull request #353 from tsloughter/test-link-event-attr
fix for links on a span and fix testing of span data
2022-02-03 06:04:08 -07:00
Tristan Sloughter e0e315b1e8
Merge branch 'main' into test-link-event-attr 2022-02-03 05:57:45 -07:00
Tristan Sloughter ccc6138f23
Merge pull request #354 from wuunder/use_opentelemetry_timestamp
Fix bug related to event timestamp format.
2022-02-03 05:28:37 -07:00
Derek Kraan eb4bc7cd6c Fix bug related to timestamp format.
The exporter assumes that we are using `opentelemetry:timestamp/0`,
which returns a timestamp in the erlang native format. This commit
cleans up use of `erlang:system_time/1`.
2022-02-03 10:59:51 +01:00
Tristan Sloughter a3f5aaf495
fix tests of attribute, link and event adding to spans 2022-02-01 17:44:59 -07:00
Tristan Sloughter 5144bc0aac
support new links as a link record 2022-02-01 17:44:32 -07:00
Tristan Sloughter 5727b2c0c2
Merge pull request #348 from tsloughter/scheme-port
use the default port of the scheme (http/https) instead of default OTLP port
2022-02-01 10:34:51 -07:00
Tristan Sloughter a30792af1c
Merge branch 'main' into scheme-port 2022-02-01 10:19:16 -07:00
Tristan Sloughter 2b8d7b2a6d
Merge pull request #349 from indrekj/fix-metrics-exporter
Fix using OTEL_METRICS_EXPORTER env variable
2022-01-11 06:28:48 -07:00
Indrek Juhkam 48c4e598d2
Fix traces_exporter type spec
traces_exporter can be "none" in which case the value will be undefined.
2022-01-11 15:22:12 +02:00
Tristan Sloughter b8cccd01e1
use default http or https port if uri string is given 2022-01-11 06:15:39 -07:00
Indrek Juhkam 525f0e3007
Fix using OTEL_METRICS_EXPORTER env variable
Previously, when env included `OTEL_METRICS_EXPORTER=none`, then the app
start failed with:

```
** (Mix) Could not start application opentelemetry: exited in: :opentelemetry_app.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (KeyError) key :metrics_exporter not found
            (opentelemetry 1.0.0) [redacted app]/deps/opentelemetry/src/otel_configuration.erl:194: :otel_configuration.update_config_map/5
            (stdlib 3.15) lists.erl:1267: :lists.foldl/3
            (opentelemetry 1.0.0) [redacted app]/deps/opentelemetry/src/otel_configuration.erl:98: :otel_configuration.general/2
            (stdlib 3.15) lists.erl:1267: :lists.foldl/3
            (opentelemetry 1.0.0) [redacted app]/deps/opentelemetry/src/opentelemetry_app.erl:27: :opentelemetry_app.start/2
            (kernel 8.0) application_master.erl:293: :application_master.start_it_old/4
```

This was because metrics_exporter was not defined in the configuration
map and the code tried to update the existing value:

```
    try transform(Transform, Value) of
        TransformedValue ->
            ConfigMap#{Key := TransformedValue}
```

Other solution would have been to use `maps:put` but I think it makes
more sense to treat it similarly to `traces_exporter`.
2022-01-11 11:49:02 +02:00
Tristan Sloughter cec6fb806c
remove unneeded parse_endpoint clause 2022-01-09 16:43:27 -07:00
Tristan Sloughter 2fa1eda0b7
Merge pull request #346 from tsloughter/strict-trace-context
Tracestate: Keep last value for duplicate key
2022-01-07 17:23:40 -07:00
Tristan Sloughter 4cc68b09dc
Merge branch 'main' into strict-trace-context 2022-01-07 17:19:56 -07:00
Tristan Sloughter c7e5ed08d8
w3c tracestate: spec now says to keep one of duplicate keys 2022-01-07 12:10:39 -07:00
Tristan Sloughter 133cf30974
allow dialyzer to run on all funtions in exporter
Since we don't count the drops when the data is just bad we can
use a list comphrension and remove the dialyzer ignore setting.
2022-01-07 10:21:39 -07:00
Tristan Sloughter 98588dffb2
fix html tags in docs 2022-01-07 10:21:39 -07:00
Tristan Sloughter 354b286285
fix link to tracer spec in docs 2022-01-06 13:33:45 -07:00
Tristan Sloughter 8e09c54dcb
fix type ref to time_unit in docs 2022-01-06 13:33:27 -07:00
Bryan Naegele 3e3281ce28
Merge pull request #344 from davydog187/patch-1
SimpleBet -> Simplebet
2022-01-05 12:13:51 -07:00
Dave Lucia ba63e384df
SimpleBet -> Simplebet
We changed our branding a little while back :)
2022-01-05 13:51:28 -05:00
Tristan Sloughter 4d031fd906
Merge pull request #343 from tsloughter/badges-w3c
additional badges, fix w3c interop CI and correct the requirements
2022-01-04 16:27:42 -07:00
Tristan Sloughter 9b59e3cc83
fix w3c interop github action 2022-01-04 15:55:30 -07:00
Tristan Sloughter d72038b253
correct the erlang and elixir min requirements 2022-01-04 13:36:20 -07:00
Tristan Sloughter 802df22116
add badges for hex packages 2022-01-04 13:34:37 -07:00
Tristan Sloughter f12732d2b6
Merge pull request #342 from tsloughter/cut-1.0.0
Cut 1.0.0
2022-01-04 11:07:17 -07:00
Tristan Sloughter 1a42d7f909
give extra context in readme on git deps usage 2022-01-04 08:45:44 -07:00
Tristan Sloughter 532c4b1850
cleanup leftover readme section on releases 2022-01-04 08:32:34 -07:00
Tristan Sloughter aacbd757a0
Update CHANGELOG.md
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2022-01-04 08:23:30 -07:00
Tristan Sloughter d3b6c7014b
improve README's for top level, API and exporter 2022-01-03 17:05:08 -07:00
Tristan Sloughter 698a7873d9
bump to 1.0.0 2022-01-03 16:41:28 -07:00
Tristan Sloughter 1b90aa7791
Merge pull request #341 from tsloughter/protocol-compression-env
update and add exporter options
2022-01-03 14:58:09 -07:00
Tristan Sloughter e16ffd3fae
update exporter readme and default ports 2022-01-03 14:40:12 -07:00
Tristan Sloughter 956ffea5e1
add exporter options for protocol and compression 2022-01-03 14:37:17 -07:00
Tristan Sloughter a22fb0e8ad
Merge pull request #340 from indrekj/fix-links
Fix exporting spans with links
2022-01-03 10:45:43 -07:00
Indrek Juhkam 53497963a6
Fix exporting spans with links
This fixes exporting spans that include links. Previously these resulted
in this error:
```
exception error: bad map: {attributes,128,infinity,0,#{}}
```

The test is not the most sophisticated one, but it at least catches this
particular error.
2022-01-03 19:33:13 +02:00
Tristan Sloughter 724460ca45
Merge pull request #337 from tsloughter/more-codecov
update codecov action and add zipkin/experimental coverage
2021-12-30 16:15:54 -07:00
Tristan Sloughter 54f09c57a2
Merge branch 'main' into more-codecov 2021-12-30 15:46:09 -07:00
Tristan Sloughter 016500c50d
Merge pull request #338 from tsloughter/exporter-boot
Exporter boot
2021-12-30 15:45:54 -07:00
Tristan Sloughter 8ccf52e649
Merge branch 'main' into exporter-boot 2021-12-30 15:27:28 -07:00
Tristan Sloughter 1800a0bb78
Merge branch 'main' into more-codecov 2021-12-30 15:26:04 -07:00
Tristan Sloughter 036cf67715
improve exporter init process
In batch_processor and simple_processor the exporter:init is moved
out of the gen_statem `init`. If it fails (returns `undefined`)
then the `init` will be attempted again each time spans are to
be exported.

The only issue is the warnings about failing to init the exporter
will continue to print forever if it can never initialize. We
can't simply stop trying to init if the failure is one that can
never resolve on its own because the exporter can be changed at
anytime by the user.

This is not meant to be used for retry logic and has no exp
backoff. It is only meant to deal with issues like the exporter's
deps not being started when the SDK tries to init the exporter and
it will soon successfully init because the release is in the
process of booting.
2021-12-29 17:06:47 -07:00
Tristan Sloughter c845d3e560
remove Zach Daniel from maintainers list in readme 2021-12-29 12:37:18 -07:00
Tristan Sloughter 0e3cd2476e
Merge pull request #336 from tsloughter/elixir-attributes-type
elixir span docs: fix reference to attributes type
2021-12-28 16:13:48 -07:00
Tristan Sloughter eef2d6ebf3
update codecov action and add zipkin coverage 2021-12-28 14:02:35 -07:00
Tristan Sloughter 53545f4ddf
fix bugs in elixir api docs example code 2021-12-28 09:32:49 -07:00
Tristan Sloughter 3421566ef1
elixir span docs: fix reference to attributes type 2021-12-28 09:15:14 -07:00
Tristan Sloughter 0df19fdc2c
Merge pull request #335 from tsloughter/add-event-map
events: accept map for attributes on an event
2021-12-28 09:08:56 -07:00
Tristan Sloughter 09cd16d8cc
Merge branch 'main' into add-event-map 2021-12-28 09:04:03 -07:00
Tristan Sloughter d7ebc6fa52
Merge pull request #334 from tsloughter/cleanup-rc.4
post rc.4 cleanup
2021-12-28 09:03:36 -07:00
Tristan Sloughter 4d59901489
bump API to 1.0.0-rc.4.1 2021-12-28 08:53:34 -07:00
Tristan Sloughter 8d078fe261
events: accept map for attributes on an event 2021-12-28 05:31:41 -07:00
Tristan Sloughter be0f1788b7
updates to README
Remove hex.pm badge because it points to 0.6.0 and no way to tell
it to point to 1.0.0-rc.4 (or any RC release). Add it back when
we go 1.0.0.

Improved some of the docs about releases.

Add people missing from approvers and maintainers.
2021-12-27 13:53:53 -07:00
Tristan Sloughter c4c78fc80b
update approvers and maintainers in readme 2021-12-27 13:13:48 -07:00
Tristan Sloughter e1aa0ddb6a
remove ununsed type tracer_ctx 2021-12-27 13:13:36 -07:00
Tristan Sloughter 1ce864d170
add note in exporter README about supported proto vsn 2021-12-27 08:28:44 -07:00
Tristan Sloughter f8a5e7ef8a
remove VERSION from list of package files in api mix.exs 2021-12-27 08:23:52 -07:00
Tristan Sloughter 46de081c05
Merge pull request #333 from tsloughter/bump-rc4
bump version to 1.0.0-rc.4
2021-12-27 07:23:57 -07:00
Tristan Sloughter 75d0e8246a
Merge branch 'main' into bump-rc4 2021-12-26 16:32:09 -07:00
Tristan Sloughter 6585266970
Merge pull request #332 from bryannaegele/value-guards
Remaining validations
2021-12-26 16:31:40 -07:00
Bryan Naegele afda6b650c Feedback 2021-12-26 12:00:32 -07:00
Bryan Naegele baf12d6a66 Add tuple support back 2021-12-25 19:06:22 -07:00
Tristan Sloughter 4fb0ce14a2
bump version to 1.0.0-rc.4
The API Application no longer uses a VERSION file because mix.exs
grabs the version to use from the src/opentelemetry_api.app.src
file, so it is no longer needed.

The Exporter Application sets its version manually in .app.src
so that its versions can be tracked separately from the SDK.
2021-12-25 17:58:45 -07:00
Bryan Naegele 5f22cdfdda Lists are validated to be homogenous 2021-12-25 15:18:27 -07:00
Bryan Naegele 9b36e39b82 Update changelog 2021-12-25 15:18:23 -07:00
Bryan Naegele 318f127ee7 More test coverage 2021-12-25 15:16:38 -07:00
Bryan Naegele cb9bbbb725 Elixir test 2021-12-25 15:16:38 -07:00
Bryan Naegele 3d6aec3f71 Just use map filter 2021-12-25 15:16:38 -07:00
Bryan Naegele da21994939 Elixir updates 2021-12-25 15:16:38 -07:00
Bryan Naegele 9374b1d825 Don't validate or track attr validation drops 2021-12-25 15:16:38 -07:00
Bryan Naegele 2b52be8a61 Add remaining validations to the API 2021-12-25 15:16:29 -07:00
Tristan Sloughter b8185bdb8d
Merge pull request #331 from tsloughter/schema-url
Support for Schema URLs on the Resource and Tracer (Instrumentation Library)
2021-12-25 13:41:12 -07:00
Tristan Sloughter b4a85e1265
clean up type specs for get_ and set_ tracer 2021-12-25 09:32:21 -07:00
Tristan Sloughter 79f2811900
Merge branch 'main' into schema-url 2021-12-25 09:07:54 -07:00
Tristan Sloughter 84e7cf9a27
Merge pull request #306 from kw7oe/add-gzip-compression-option-for-exporter
Add gzip compression option for exporter
2021-12-24 09:08:17 -07:00
Tristan Sloughter 4734d527f8
always check for unicode strings, not latin1 2021-12-24 08:16:01 -07:00
Tristan Sloughter 8889fbd2d5
remove register_tracer. always use get_tracer
This fits the spec and other implementations of otel where the
term register is only used when talking about TracerProviders.
We don't currently expose a register for providers and I don't
know that we will. Providers are processes and I'd say them
starting and registering at atom name is what their "registering"
is.
2021-12-23 16:43:55 -07:00
Tristan Sloughter 69a40f9987
support schema_url in tracer 2021-12-22 15:22:20 -07:00
Tristan Sloughter 660099da44
add schema_url to instrumentation_library 2021-12-22 10:09:21 -07:00
Tristan Sloughter a40046d344
use binary string for resource attributes 2021-12-22 10:09:07 -07:00
Tristan Sloughter 86b5715257
fix config reading for deny_list and resource detectors 2021-12-22 06:03:29 -07:00
Tristan Sloughter 3919fd6652
support schema_url in resource 2021-12-21 09:49:50 -07:00
Kai 94ddb7f27e
Merge branch 'main' into add-gzip-compression-option-for-exporter 2021-12-18 11:29:35 +08:00
Tristan Sloughter 0bc0f4d38e
Merge pull request #325 from tsloughter/zipkin
move zipkin exporter to main repo
2021-12-17 19:40:14 -07:00
Tristan Sloughter 5d2f42926f
update zipkin exporter for new attributes records 2021-12-17 18:24:15 -07:00
Tristan Sloughter 14d3e6af8b
fix service name lookup in zipkin exporter to use charlist key 2021-12-17 17:18:41 -07:00
Tristan Sloughter 7ddf70664c
using same zipkin address in github actions as local 2021-12-17 17:18:41 -07:00
Tristan Sloughter da5155dedd
remove apps old build status badges from readmes 2021-12-17 17:18:41 -07:00
Tristan Sloughter 7a11fcce01
move zipkin exporter to main repo 2021-12-17 17:18:41 -07:00
Tristan Sloughter f675aaae8a
Merge pull request #329 from tsloughter/attributes-map
Support limits on attributes, links and events
2021-12-17 15:58:10 -07:00
Tristan Sloughter a7a579f216
use attributes:set for resource merging 2021-12-17 15:26:41 -07:00
Tristan Sloughter f2733f3e0e
simplify add_events length check against limit 2021-12-17 13:48:38 -07:00
Tristan Sloughter 1a6569f427
use maps for event/link and their records to the SDK 2021-12-17 05:51:59 -07:00
Tristan Sloughter bdb295b8f6
add entry to changelog about attribute, link and event limits 2021-12-16 12:07:21 -07:00
Tristan Sloughter d75a096ae4
fix attribute limit to override existing keys even if limit reached 2021-12-16 12:07:03 -07:00
Tristan Sloughter 563c71d4d4
update elixir tests for new links, events and attribute limits 2021-12-16 11:04:20 -07:00
Kai 7ed0d458f7
Merge branch 'main' into add-gzip-compression-option-for-exporter 2021-12-16 10:17:16 +08:00
Tristan Sloughter 9e40f0657e
limits on the number of links, events, attributes and their value size
Attribute limits can be set per event, link and span, as well as
general attribute limits that are used if no specific limits are
set for the individual type.

The number of attributes, links and events dropped do to being
over the limit is tracked and required changing each to be a
record that holds both the limits to apply and how many have
been dropped.
2021-12-15 18:40:06 -07:00
Tristan Sloughter c088830d3b
support limits on attribute count and value length 2021-12-15 18:40:06 -07:00
Tristan Sloughter 3d56c1134f
Merge pull request #328 from tsloughter/app-env-config
move the rest of application env vars to configuration map
2021-12-15 18:39:14 -07:00
Tristan Sloughter c9e0e545c7
move the rest of application env vars to configuration map 2021-12-14 18:51:39 -07:00
Kai 7ab8b2378e
Merge branch 'main' into add-gzip-compression-option-for-exporter 2021-12-13 21:35:44 +08:00
Tristan Sloughter 70681ede9c
Merge pull request #327 from tsloughter/span-limits
Configuration improvements and span limit settings
2021-12-13 06:21:04 -07:00
Tristan Sloughter 68f0341de1
relax merge_list_with_environment type spec so exporter can use it 2021-12-13 06:17:06 -07:00
Kai 63b6fe6ebe
Merge branch 'main' into add-gzip-compression-option-for-exporter 2021-12-13 21:10:29 +08:00
Tristan Sloughter bd436071cb
Merge branch 'main' into span-limits 2021-12-13 06:05:00 -07:00
Tristan Sloughter 20c89cfd94
Merge pull request #316 from tsloughter/single-tracer-registry
tracers: store startup created tracers the same way as user created
2021-12-13 06:04:51 -07:00
Tristan Sloughter 1c0d543b09
better handling of configuration values
these changes ensure all configuration goes through transform
checks to verify their type, as best we can. Before only the
values from OS environment variables would be transformed. This
could lead to configuration values like "string" for a key
like attribute_count_limit that requires an integer.
2021-12-09 13:53:30 -07:00
Tristan Sloughter f6ddeee5e0
use defaults if unable to parse configuration value 2021-12-07 05:07:51 -07:00
Tristan Sloughter 98b27004ca
add span limits record and configuration setup 2021-12-06 16:05:35 -07:00
kw7oe a821790015 Add test for grpc with gzip compression 2021-11-29 17:09:35 +08:00
kw7oe 62af6cc066 Add gzip compression support for grpc exporter 2021-11-28 16:20:35 +08:00
kw7oe d2ce9883a4 Add test for http_protobuf with gzip compression 2021-11-28 16:20:35 +08:00
kw7oe 9a5922b183 Implement compression for http_protobuf 2021-11-28 16:20:35 +08:00
kw7oe a964d6be3d Add compression config to exporter state 2021-11-28 16:20:35 +08:00
Tristan Sloughter de3ecacc6c
Merge branch 'main' into single-tracer-registry 2021-11-26 13:07:10 -07:00
Tristan Sloughter bad9d42e4b
Merge pull request #314 from tsloughter/trace-protos-0.11.0
exporter: update trace protos to v0.11.0
2021-11-26 12:22:50 -07:00
Tristan Sloughter 09dafecaf0
Merge branch 'main' into trace-protos-0.11.0 2021-11-24 15:02:05 -07:00
Tristan Sloughter 8709fc2ae6
tracers: store startup created tracers the same way as user created
To simplify the understanding of tracer registration and fetching
this removes the separation between tracers registered on startup
for each application and those registered by a user or other code
at runtime.

Now there is a map to lookup the application name for a module
which is used to lookup the tracer, instead of before where the
map lookup actually got the tracer (meaning the tracer record was
duplicated and stored for every module!).

This means a user registering a tracer can override the tracer
registered at startup for an application name if they use the same
name, but I think this is sort of expected behavior so not an issue.

The change shouldn't effect much, if any, existing user code since
it almost always that tracers are fetched behind the scenes by
the macros.
2021-11-24 13:47:10 -07:00
Tristan Sloughter 3aeec46aad
Merge pull request #315 from qdentity/dvic-docs-local_parent_not_sampled
Fix docs local_parent_not_sampled
2021-11-24 10:39:47 -07:00
dvic 6a9cc89e57
Fix docs local_parent_not_sampled 2021-11-24 14:57:23 +01:00
Tristan Sloughter 9b6f9c83f6
Merge branch 'main' into trace-protos-0.11.0 2021-11-20 15:59:17 -07:00
Łukasz Jan Niemier ba922c2ed4
Merge pull request #313 from kianmeng/fix-typos
Fix typos
2021-11-20 12:09:46 +01:00
Tristan Sloughter 0d69c0fbbc
exporter: update trace protos to v0.11.0 2021-11-19 16:33:07 -07:00
Tristan Sloughter b0eb445c05
Merge branch 'main' into fix-typos 2021-11-18 16:13:12 -07:00
Tristan Sloughter c845baa9d6
Merge pull request #294 from tsloughter/http-ssl
add ssl options support to httpc exporter
2021-11-18 16:11:21 -07:00
Tristan Sloughter ce313b99dc
Merge branch 'main' into http-ssl 2021-11-18 15:52:36 -07:00
Tristan Sloughter ae88d88ed4
Merge pull request #310 from tsloughter/id-generators
make trace/span id generation customizable
2021-11-18 14:55:29 -07:00
Tristan Sloughter fa8ae84110
pin otel collecto image for tests 2021-11-18 14:50:20 -07:00
Kian-Meng, Ang 82d5802672 Fix typos 2021-11-18 11:56:01 +08:00
Tristan Sloughter 6075c25323
add junit/surefire action to view failures in PR 2021-11-13 11:37:24 -07:00
Tristan Sloughter e71c853eb4
make trace/span id generation customizable
A behaviour, otel_id_generator, is added which has callbacks for
generating trace and span ids, along with the default versions
of those functions.

The implementation to use is kept in the tracer record.
2021-11-12 18:14:18 -07:00
Tristan Sloughter 0647ff0323
remove otp 21 from CI 2021-11-11 16:59:49 -07:00
Tristan Sloughter fb48673984
Merge branch 'main' into http-ssl 2021-11-11 08:32:12 -07:00
Tristan Sloughter 590d87f4cb
Merge pull request #309 from isaacsanders/patch-1
fix: Removes macro that references missing function
2021-11-10 16:43:11 -07:00
Isaac Sanders ecef326e11
fix: Removes macro that references missing function 2021-11-10 14:32:14 -06:00
Tristan Sloughter afcfc5fbea
exporter: use tls_cetificate_check for secure HTTPS requests
The options from tls_certificate_check can be replaced by
the user through an added ssl options configuration for the
httpc exporter.
2021-11-10 13:08:03 -07:00
Tristan Sloughter b0f4c6b436
Merge pull request #308 from tsloughter/batch-repeat-timeout
batch_processor: go to idle state after export timeout
2021-11-09 07:59:30 -07:00
Tristan Sloughter 4a05b37b0d
Merge branch 'main' into batch-repeat-timeout 2021-11-08 07:09:32 -07:00
Tristan Sloughter 17bc4086e8
Merge pull request #307 from tsloughter/no-zero-export
skip exporting if batch table is empty
2021-11-07 07:00:24 -07:00
Tristan Sloughter 9a80c505b6
batch_processor: go to idle state after export timeout 2021-11-07 06:55:53 -07:00
Tristan Sloughter beec4e3ed0
Merge branch 'main' into no-zero-export 2021-11-06 05:51:56 -06:00
Tristan Sloughter b77babdff0
Merge pull request #304 from tsloughter/simple-processor
add simple span processor
2021-11-06 05:51:43 -06:00
Tristan Sloughter 49b563c7dc
simple_processor: transition to idle after exporter timeout
Since the simple_processor is only exporting a single span and
does so based on a blocking call when a span ends there is no
need to do a `repeat_state` after the exporting time out fails.
The next export will be done if there is a span end message in
the processor's queue.
2021-11-05 17:03:27 -06:00
Tristan Sloughter 39094da031
skip exporting if batch table is empty 2021-11-04 16:22:33 -06:00
Tristan Sloughter 9193a0fb33
add simple span processor
The Simple Span Processor does a blocking call when ending a span
that returns after the span is exported.
2021-11-04 14:48:07 -06:00
Tristan Sloughter c47a3f2796
Merge pull request #303 from tsloughter/ex-app-tracer
use get_application_tracer in Elixir macros
2021-11-01 14:57:23 -06:00
Tristan Sloughter 21bec97ef8
Merge branch 'main' into ex-app-tracer 2021-11-01 12:24:38 -06:00
Tristan Sloughter f7bd7edaf1
use get_application_tracer in Elixir macros
The Erlang macros already properly use get_application_tracer.
The reason to use get_application_tracer is the macros lookup
the tracer for the particular application by module name.
2021-11-01 12:23:01 -06:00
Tristan Sloughter aa1ed7b005
Merge pull request #302 from tsloughter/env-service-name
add support for OTEL_SERVICE_NAME environment variable
2021-10-30 08:31:51 -06:00
Tristan Sloughter 97f8106d62
Merge branch 'main' into env-service-name 2021-10-30 08:28:13 -06:00
Tristan Sloughter 7e9b40a0e5
add support for OTEL_SERVICE_NAME environment variable 2021-10-29 12:31:35 -06:00
Tristan Sloughter a9ef55b39e
fix provider force_flush to use passed ServerRef 2021-10-29 12:25:16 -06:00
Tristan Sloughter 2b6a188c9d
Merge pull request #301 from tsloughter/exporter-binary-string-host
exporter: support hosts and paths as binary or list strings
2021-10-28 17:38:50 -06:00
Tristan Sloughter 9b25285022
exporter: support hosts and paths as binary or list strings 2021-10-28 14:57:02 -06:00
Tristan Sloughter 2170a843df
Merge pull request #296 from tsloughter/rm-sampler-opt
remove sampler option to start_span and with_span
2021-10-26 16:03:28 -06:00
Tristan Sloughter 0031138bb1
Merge branch 'main' into rm-sampler-opt 2021-10-26 15:58:03 -06:00
Tristan Sloughter ead6ae184e
Merge pull request #297 from tsloughter/force-flush
add force_flush to tracer provider and span processors
2021-10-26 15:18:55 -06:00
Tristan Sloughter 413e62b700
add force_flush to tracer provider and span processors 2021-10-26 15:11:19 -06:00
Tristan Sloughter 2acb722c6e
Merge pull request #298 from tsloughter/provider-behaviour
make TracerProvider simply implement a gen_server
2021-10-26 14:46:14 -06:00
Tristan Sloughter ed27b4a098
Merge branch 'main' into provider-behaviour 2021-10-26 14:29:01 -06:00
Tristan Sloughter bc898b869b
Merge pull request #300 from fr0stbyte/fr0stbyte/fix_error_logging
allowing the stacktrace to be logged
2021-10-26 12:43:23 -06:00
fr0stbyte dfab59626f allowing the stacktrace to be logged 2021-10-26 13:51:58 -04:00
Tristan Sloughter 106e044f8d
remove sampler option to start_span and with_span 2021-10-25 16:22:47 -06:00
Tristan Sloughter 4d1a65e809
make TracerProvider simply implement a gen_server
The API defines the functions a user calls to interact with the
TracerProvider but the handling of the gen_server calls is done
in another module. In this case the other module is in the SDK
application.

otel_tracer_server registers itself with the name
otel_tracer_provider so it acts as the default global provider.

If multiple SDK's attempt to register as the default providers
startup will fail, by design.
2021-10-25 13:58:17 -06:00
Tristan Sloughter fab724a811
Merge pull request #292 from tsloughter/exporter-docs
improve exporter module documentation and readme
2021-10-18 12:29:17 -06:00
Tristan Sloughter 21906cf32b
Merge branch 'main' into exporter-docs 2021-10-18 12:23:14 -06:00
Tristan Sloughter 00c9eaaad5
fix exporter scheme typespec 2021-10-18 12:22:53 -06:00
Tristan Sloughter 52f24d86a2
Merge pull request #293 from tsloughter/w3c-interop-with-span
W3c interop tests now run in CI
2021-10-18 10:25:37 -06:00
Tristan Sloughter 01b22fa44d
add github action workflow for w3c trace context interop 2021-10-15 16:15:18 -06:00
Tristan Sloughter 6a483c3f41
fix up w3c interop test runner to use with_span macro 2021-10-15 12:52:00 -06:00
Tristan Sloughter 6268ef85ff
use empty tracestate when it fails to decode 2021-10-15 12:51:39 -06:00
Tristan Sloughter 3ec419f720
include description of os vars in module docs 2021-10-15 07:57:58 -06:00
Tristan Sloughter 698b225700
support all type of scheme for now 2021-10-15 07:56:31 -06:00
Tristan Sloughter 3476889031
Merge pull request #291 from tsloughter/rc3-api-2
bump api version to 1.0.0-rc.3.2
2021-10-13 17:26:36 -06:00
Tristan Sloughter a21cc72a81
improve exporter module documentation and readme 2021-10-13 17:24:07 -06:00
Tristan Sloughter 4f4bb1ca22
update changelog for 1.0.0-rc.3.1 and rc.3.2 2021-10-13 15:38:54 -06:00
Tristan Sloughter b76ebc51df
bump api versoin to 1.0.0-rc.3.2 2021-10-13 15:08:21 -06:00
Bryan Naegele b41aee52d1
Merge pull request #290 from qdentity/fix-extract-span-ctx-from-string
Fix otel_propagator_trace_context:extract/1 missing undefined check
2021-10-13 13:16:51 -06:00
Damir Vandic ec2335b8bd
Merge branch 'main' into fix-extract-span-ctx-from-string 2021-10-13 20:16:52 +02:00
dvic 17f9f2d512
Fix otel_propagator_trace_context:extract/1 missing undefined check 2021-10-13 20:14:12 +02:00
Tristan Sloughter f58196f7e5
Merge pull request #289 from tsloughter/rc3-doc-vsn-cleanup
couple things I noticed while publishing packages
2021-10-13 11:06:05 -06:00
Tristan Sloughter df3e2f143c
update other versions to rc3 2021-10-12 16:35:50 -06:00
Tristan Sloughter f997e7a65f
fix module docs block in b3 modules 2021-10-12 16:35:28 -06:00
Tristan Sloughter 82337deb21
Merge pull request #288 from tsloughter/bump-rc3
bump version to 1.0.0-rc.3
2021-10-12 13:00:01 -06:00
Tristan Sloughter 18be678009
Update CHANGELOG.md
Co-authored-by: Bryan Naegele <bryannaegele@users.noreply.github.com>
2021-10-12 12:06:18 -06:00
Tristan Sloughter 34baaa21ae
Update CHANGELOG.md
Co-authored-by: Bryan Naegele <bryannaegele@users.noreply.github.com>
2021-10-12 12:06:09 -06:00
Tristan Sloughter 7ad5ec1ef3
format changelog according to https://keepachangelog.com/en/1.0.0/ 2021-10-12 10:46:40 -06:00
Tristan Sloughter 6bfcf669a1
bump version to 1.0.0-rc.3 2021-10-11 18:18:19 -06:00
Tristan Sloughter 730124ee96
Merge pull request #287 from tsloughter/single-tracer-term
separate application tracer registration from user named tracers
2021-10-08 16:25:33 -06:00
Tristan Sloughter 64cbc0a4ce
separate application tracer registration from user named tracers
Because `persistent_term:put` slows down as the number of terms
grows a project with thousands of modules can cause startup to
timeout as it sets a term for every module in it. This patch
replaces that term for each module with a single term containing
a map of `module => tracer`.

Users must be able to register named tracers at runtime and we
want to not trigger a global GC by updating the tracer map
used for module to tracer mapping. So any user registered tracer
will have its own `persistent_term`.

The macro for looking up a tracer used in macros like `?with_span`
now looks up the tracer by looking up the module in the
"application tracers" (the persistent term containing the map).
While a user looking up a named tracer will do so with the function
`opentelemetry:get_tracer/1` which looks directly for a term with
that name.

This means a user could register a tracer with the same name as a
module. Whether this is good or bad or needs a check to guard
against is not covered by this PR.
2021-10-08 11:48:21 -06:00
Tristan Sloughter 51ce24eec7
Merge pull request #258 from tsloughter/exporter-exception-logs
improve exporter failure logs and include stacktrace
2021-10-07 16:24:20 -06:00
Tristan Sloughter e2ae00be80
improve exporter failure logs and include stacktrace 2021-10-06 20:09:12 -06:00
Tristan Sloughter a7ddda6db6
Merge pull request #286 from fr0stbyte/radu/span_end_time2
allows for optional end span timestamp
2021-10-05 17:00:56 -06:00
fr0stbyte 4b018e8fee adding undefined as possible type for Timestamp 2021-10-05 18:43:35 -04:00
fr0stbyte 01436f6d24 adding spec for tracer.ex end_span 2021-10-05 18:30:05 -04:00
Radu Brumariu 47b5220f3f
Update apps/opentelemetry_api/lib/open_telemetry/tracer.ex
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2021-10-05 16:27:21 -04:00
fr0stbyte e33af34ddc updating otp versions 2021-10-05 16:04:05 -04:00
fr0stbyte a48cc9a8ec updating the macros 2021-10-05 14:37:47 -04:00
fr0stbyte cfa9dfa8d1 localizing defaults in otel_span_utils 2021-10-05 14:18:14 -04:00
Radu Brumariu 77b5b9c269
Update apps/opentelemetry_api/src/otel_span.erl
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2021-10-05 09:39:25 -04:00
fr0stbyte 3e404ab699 simplify end_trace in tracer 2021-10-04 14:30:39 -04:00
fr0stbyte dc8197520a add end_span/1 in tracer.ex 2021-10-04 14:30:39 -04:00
fr0stbyte 323c883e6f address feedback 2021-10-04 14:30:39 -04:00
fr0stbyte e8314200f1 fix syntax error 2021-10-04 14:30:39 -04:00
fr0stbyte 650862f0eb adding end_span/2 2021-10-04 14:30:39 -04:00
Tristan Sloughter b70723b58e
Merge pull request #281 from indrekj/b3-single
Add B3 single propagation format support
2021-10-04 07:10:46 -06:00
Indrek Juhkam 13b7dba5c4
Add B3 single propagation format support
[B3 single format][1] looks like this: `b3={TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}`,
where the last two fields are optional.

[OpenTelemetry B3 requirements][2]:

B3 has both single and multi-header encodings. It also has semantics
that do not map directly to OpenTelemetry such as a debug trace flag,
and allowing spans from both sides of request to share the same id. To
maximize compatibility between OpenTelemetry and Zipkin implementations,
the following guidelines have been established for B3 context
propagation.

When extracting B3, propagators:
* MUST attempt to extract B3 encoded using single and multi-header
  formats. The single-header variant takes precedence over the
  multi-header version.
* MUST preserve a debug trace flag, if received, and propagate it with
  subsequent requests. Additionally, an OpenTelemetry implementation
  MUST set the sampled trace flag when the debug flag is set.
* MUST NOT reuse X-B3-SpanId as the id for the server-side span.

When injecting B3, propagators:
* MUST default to injecting B3 using the single-header format
* MUST provide configuration to change the default injection format to
  B3 multi-header
* MUST NOT propagate X-B3-ParentSpanId as OpenTelemetry does not support
  reusing the same id for both sides of a request.

[1]: https://github.com/openzipkin/b3-propagation#single-header
[2]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-requirements
2021-10-04 15:59:44 +03:00
Tristan Sloughter 29af143533
Merge pull request #284 from tsloughter/rm-tracer-span
remove unneeded current span functions from otel_tracer
2021-10-01 16:51:07 -06:00
Tristan Sloughter 0df1e7da26
remove unneeded current span functions from otel_tracer
`?end_span` is updated to work update the current context through
calling `otel_tracer:set_current_span`. In order to still return
the new `SpanCtx` this function was also changed to return the
`SpanCtx` that was passed to it.
2021-10-01 14:12:06 -06:00
Tristan Sloughter 700e2ea0fa
Merge pull request #285 from chalin/chalin-drop-website-docs-2021-10-01
Drop website_docs and docs_update workflow
2021-10-01 13:42:09 -06:00
Patrice Chalin e09b654569 Drop website_docs and docs_update workflow 2021-10-01 15:08:48 -04:00
Tristan Sloughter 9565e4f4f1
Merge pull request #268 from kw7oe/generate-docs-with-exdoc
Generate docs with ExDoc
2021-09-26 07:19:19 -06:00
Tristan Sloughter cf1b218d2a
Merge branch 'main' into generate-docs-with-exdoc 2021-09-24 14:52:25 -06:00
Tristan Sloughter 4905c93ac7
Merge pull request #273 from tsloughter/composite
Update propagators with composite
2021-09-24 14:48:00 -06:00
Tristan Sloughter 45784c3f27
improve type specs in propagator modules 2021-09-24 12:47:39 -06:00
Tristan Sloughter f772491057
fix otel_configuration to set text_map_propagators option 2021-09-24 09:12:56 -06:00
Tristan Sloughter 1c898d468f
cleanup old uses of b3 to b3multi 2021-09-24 06:05:24 -06:00
Tristan Sloughter c1fd2fbda5
remove plural form of setting propagators from opentelemetry
To simplify the interface from opentelemetry module the user must
pass a single propagator, using a composite propagator if they
need multiple. But the confiugration `text_map_propagators` remains
and will create a composite propagator for the user.
2021-09-24 06:05:24 -06:00
Tristan Sloughter f59d27cc33
rework propagators to use a composite propagator
instead of propagators always being a list that are run in order
this PR requires a composite propagator be created if a multiple
propagators are to be used.
2021-09-24 05:30:04 -06:00
Tristan Sloughter a7070a83f9
support manually specifying propagators in inject/extract
Since a new option to inject/extract was needed I've added 2 new
functions `inject_from` and `extract_to` that take Contexts as
the first argument. Otherwise there is a lot of overloading
of types of arguments required.
2021-09-24 05:30:04 -06:00
Tristan Sloughter bac424970b
Add a changelog file 2021-09-24 05:30:04 -06:00
Tristan Sloughter db8f00ad53
make tracestate default to an empty list 2021-09-24 05:30:04 -06:00
Tristan Sloughter d59c450819
Update apps/opentelemetry_api/test/custom_propagator.erl
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2021-09-24 05:30:04 -06:00
Tristan Sloughter efe9fd8832
Update apps/opentelemetry/src/otel_tracer_default.erl
Co-authored-by: Bryan Naegele <bryannaegele@users.noreply.github.com>
2021-09-24 05:30:03 -06:00
Tristan Sloughter 05c05c35fb
documenting modules and functions related to propagators 2021-09-24 05:30:03 -06:00
Tristan Sloughter b6bd18e24a
rewrite propagators
This change makes propagators use a behaviour to define the inject
and extract functions instead of being anonymous functions.

The latest Otel spec is also matched by adding functions for getting
all fields a propagator sets and allowing the overriding of the
get/set/keys functions used by inject/extract.
2021-09-24 05:29:57 -06:00
Tristan Sloughter 277c98b655
Merge pull request #272 from indrekj/b3multi
Add b3multi option to OTEL_PROPAGATORS
2021-09-24 05:22:20 -06:00
Indrek Juhkam e98fc2db88
Add b3multi option to OTEL_PROPAGATORS
According to [OTEL Spec][1] there are `b3` and `b3multi`. The latter is
supposed to be used when [Multi B3 format][2] is used. This is exactly
what b3_propagators() currently is doing.

[1]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#general-sdk-configuration
[2]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-extract
2021-09-22 12:32:47 +03:00
Tristan Sloughter f0cf709fa6
Merge pull request #270 from indrekj/hex-ids
Expose trace IDs in hex format
2021-09-21 11:00:15 -06:00
Tristan Sloughter 61dd8bfe86
Merge branch 'main' into hex-ids 2021-09-21 05:37:27 -06:00
Fred Hebert 17d9c707c2
Merge pull request #277 from open-telemetry/tsloughter-patch-1
Update Tristan's work in README
2021-09-19 19:26:47 -04:00
Tristan Sloughter 8276df575e
Update Tristan's work in README 2021-09-19 15:35:52 -06:00
Iliia Khaprov 67f02df21e
Merge pull request #275 from open-telemetry/chore/update-names
Update Iliia name and workplace
2021-09-09 22:30:35 +02:00
Łukasz Niemier 74d457d79c
chore: update Iliia name and workplace for him and me 2021-09-09 21:10:43 +02:00
Indrek Juhkam a97f5b7f3a
Expose trace IDs in hex format
According to the [spec][1]
> The API MUST allow retrieving the TraceId and SpanId in the following forms:
>
>    Hex - returns the lowercase hex-encoded TraceId (result MUST be a 32-hex-character lowercase string) or SpanId (result MUST be a 16-hex-character lowercase string).
>    Binary - returns the binary representation of the TraceId (result MUST be a 16-byte array) or SpanId (result MUST be an 8-byte array).
>
> The API SHOULD NOT expose details about how they are internally stored.

This commit takes care of the Hex part.

[1]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#retrieving-the-traceid-and-spanid)
2021-09-01 18:19:50 +03:00
Kai d6d7a9e34d
Remove 'as docs' in docs.sh as suggested
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2021-08-22 11:30:55 +08:00
Kai 9079896ad3
Merge branch 'main' into generate-docs-with-exdoc 2021-08-21 18:31:41 +08:00
kw7oe 07645e4fb9 Configure otel and otel exporter .app.src for publishing docs to Hex.pm 2021-08-21 18:26:02 +08:00
kw7oe 8f03d3347d Add docs and fix docs formatting 2021-08-21 18:07:36 +08:00
kw7oe 297c832ad3 Generate opentelemetry_exporter docs with ExDoc 2021-08-21 17:28:01 +08:00
kw7oe 0ee49262c6 Modify VERSIONING to be Markdown file to looks better in ExDoc 2021-08-21 17:18:31 +08:00
kw7oe 9b0146c7d7 Generate opentelemetry docs with ExDoc 2021-08-21 17:13:36 +08:00
Tristan Sloughter c0487cfad5
Merge pull request #263 from qdentity/dvic-root-span-sampling
Fix root span sampling
2021-08-19 20:21:33 -06:00
Tristan Sloughter 38b964c0e2
Merge branch 'main' into dvic-root-span-sampling 2021-08-19 17:44:58 -06:00
Tristan Sloughter ea75b2aa4c
Merge pull request #267 from qdentity/dvic-non-recording-ets
Do not insert non-recording spans in ETS
2021-08-19 17:42:49 -06:00
dvic 6c680e40e6
Update for refactored otel_sampler:new function 2021-08-20 00:02:59 +02:00
dvic 7862aa5279
Update for refactored otel_sampler:new function 2021-08-20 00:00:43 +02:00
Tristan Sloughter 817f311e65
Merge branch 'main' into dvic-non-recording-ets 2021-08-19 06:25:20 -06:00
Tristan Sloughter 18121ed97d
Merge branch 'main' into dvic-root-span-sampling 2021-08-19 06:18:02 -06:00
Tristan Sloughter 871030114f
Merge pull request #261 from qdentity/dvic-refactor-sampler
Refactor otel_sampler to use callbacks for setup, should_sample, and decription
2021-08-19 06:17:35 -06:00
dvic cd4ae4d776
Use otel_span:tracestate in built-in samplers 2021-08-19 09:33:06 +02:00
dvic ad882b78df
Fix Elixir test for refactored otel_sampler:new function 2021-08-12 20:12:07 +02:00
dvic 2fbef5638a
Verify with test that non-recording span is omitted from ETS table 2021-08-12 20:08:36 +02:00
dvic c6df12a3a6
Do not insert non-recording spans in ETS 2021-08-12 19:54:30 +02:00
Damir Vandic 8c6ea20391
Merge branch 'main' into dvic-refactor-sampler 2021-08-11 14:16:20 +02:00
Tristan Sloughter 0f732f755f
Merge branch 'main' into dvic-root-span-sampling 2021-08-11 05:22:34 -06:00
Tristan Sloughter 24804a772e
Merge pull request #264 from qdentity/dvic-child-span-sampling
Add test for child span sampling issue
2021-08-11 05:22:18 -06:00
dvic eab5e9544d
Merge branch 'main' into dvic-refactor-sampler 2021-08-11 09:27:16 +02:00
Tristan Sloughter 9a04b3ff38
Merge branch 'main' into dvic-root-span-sampling 2021-08-10 16:45:15 -06:00
Tristan Sloughter bfdae7f03c
Merge branch 'main' into dvic-child-span-sampling 2021-08-10 13:22:42 -06:00
Fred Hebert c24b67cd82
Merge pull request #266 from pedro-gutierrez/pedro-gutierrez/259-grpc-endpoints-ssl-options
User defined ssl options in grpc endpoints
2021-08-10 14:11:54 -04:00
Damir Vandic 3e2c2f19a3
Merge branch 'main' into dvic-root-span-sampling 2021-08-10 17:16:06 +02:00
Damir Vandic 0c6451ca34
Merge branch 'main' into dvic-child-span-sampling 2021-08-10 17:10:16 +02:00
Pedro Gutiérrez f5ce58ae1f
Add ssl_options parsing tests 2021-08-10 16:25:20 +02:00
Pedro Gutiérrez 723b08122c
Slightly more robust endpoint parsing 2021-08-10 16:25:11 +02:00
Pedro Gutiérrez b81cc01cc4
Support grpcbox endpoints without ssl options 2021-08-10 16:25:01 +02:00
Pedro Gutiérrez 611d5e5623
Parse SSL options from grpc endpoints 2021-08-10 16:24:44 +02:00
dvic 78e65d0a66
Do not use otel_sampler_ prefix in sampler spec for built-in samplers 2021-08-09 23:31:28 +02:00
Damir Vandic 0620e056a1
Merge branch 'main' into dvic-refactor-sampler 2021-08-09 23:02:09 +02:00
Tristan Sloughter 3f795525ad
Merge pull request #265 from tsloughter/set-is-remote
use new api function from_remote_span for propagated span context
2021-08-09 08:25:08 -06:00
dvic a1cd744d9a
Add failing test for child span sampling issue 2021-08-08 20:13:21 +02:00
dvic c2909357f0
Add documentation for the built-in samplers 2021-08-08 00:21:47 +02:00
dvic 0081136aeb
Prefix all built-in sampler modules with otel_sampler_ 2021-08-08 00:09:38 +02:00
Tristan Sloughter a845aa6807
use new api function from_remote_span for propagated span context 2021-08-07 07:57:57 -06:00
dvic f3bf8a4dba
Add missing test case to all_testcases() 2021-08-06 20:48:41 +02:00
dvic 5401b3ad26
Revert introducing otel_sampler:instance() 2021-08-06 20:44:56 +02:00
dvic 2bb5262847
Revert support for attributes in built-in samplers 2021-08-06 20:39:12 +02:00
dvic 92b592c901
Remove comment in test code 2021-08-06 19:57:59 +02:00
dvic 5efd97328c
Fix parent-based sampler picking the wrong sampler, see #264 2021-08-06 17:01:07 +02:00
dvic 08e2b572b7
Add tests for root_span_sampling always_on and always_off 2021-08-06 14:23:49 +02:00
dvic 28cfcc58f3
Fix root span sampling 2021-08-05 22:21:43 +02:00
dvic acfd32ef8c
Add 'pass_attributes' test to all() 2021-08-05 19:42:14 +02:00
dvic c332b92522
Add test for otel_samplers:should_sample 2021-08-04 21:38:20 +02:00
dvic 30257ce8c9
Add tests for passing attributes to built-in samplers 2021-08-04 21:34:46 +02:00
dvic 24fb117ad4
Fix always_off sampler 2021-08-04 21:20:52 +02:00
dvic 8aacfff5e3
Refactor otel_sampler to use callbacks for setup, should_sample, and decription 2021-08-04 21:00:40 +02:00
Tristan Sloughter edfd2226fa
Merge pull request #260 from qdentity/dvic-sampler-new
Introduce otel_sampler:new/3 and fix behavior typespec
2021-08-03 16:21:24 -06:00
dvic 99633d7719
Fix formatting 2021-08-03 23:37:37 +02:00
dvic 055afa2cb3
Rename decider() to sampler_fun() 2021-08-03 23:31:02 +02:00
dvic 8ffe3ad6dd
Introduce otel_sampler:new/3 and fix behavior typespec 2021-08-03 23:13:49 +02:00
Bryan Naegele 3eff2f27a2
Merge pull request #246 from open-telemetry/status-spec-compliance
Better compliance with status spec
2021-07-13 14:54:21 -06:00
Bryan Naegele f4b7356d3f
Merge branch 'main' into status-spec-compliance 2021-07-13 13:27:17 -06:00
Bryan Naegele 9110035e6b
Merge pull request #257 from wuunder/add_guard_register_tracer
Add guard to register_tracer
2021-07-02 13:19:07 -06:00
Bryan Naegele a7b56078f4
Update apps/opentelemetry_api/src/opentelemetry.erl 2021-07-02 13:10:28 -06:00
Bryan Naegele 12144f9711
Update apps/opentelemetry_api/src/opentelemetry.erl 2021-07-02 13:08:13 -06:00
Bryan Naegele e9f8b21d19
Merge branch 'main' into add_guard_register_tracer 2021-07-02 13:04:19 -06:00
Derek Kraan 0f33c4d29f Accept binary or string, and convert internally to binary 2021-06-30 11:17:23 +02:00
Derek Kraan 306d160f30 Add guard to register_tracer
Without this, the exporter fails later if you send the second argument
as a float, for example.
2021-06-29 14:04:44 +02:00
Fred Hebert 795848b16f
Merge pull request #255 from ferd/main
Be more specific on grpcbox dependency
2021-06-14 13:03:53 -04:00
Fred Hebert 4a001bc4c8 Be more specific on grpcbox dependency
This should allow working around limitations in Mix when working from
Elixir: https://github.com/elixir-lang/elixir/issues/11062
2021-06-14 11:00:28 -04:00
Łukasz Jan Niemier efa9306f3d
Merge pull request #253 from wingyplus/header-unused
Remove unused header in otel_span_ets
2021-06-02 16:07:48 +02:00
Thanabodee Charoenpiriyakij dfd21c0235
Remove unused header in otel_span_ets
The warning detected by erlang_ls that `otel_tracer.hrl` is unused in
otel_span_ets module. This change remove this include.
2021-06-02 20:39:23 +07:00
Fred Hebert 896be9c34e
Merge pull request #254 from wingyplus/ci
Upgrade Elixir and OTP in GitHub Workflow
2021-06-02 09:37:27 -04:00
Thanabodee Charoenpiriyakij fb59106685
Merge branch 'ci-2' into ci 2021-06-02 20:29:53 +07:00
Thanabodee Charoenpiriyakij 7194b7f342
Fix build fail issues 2021-06-02 20:29:44 +07:00
Thanabodee Charoenpiriyakij 432f7de559
Add os to matrix.include
The ci will pass with error empty value on `runs-on`. The root cause is
the field `os` needs to add to matrix.include. This change fix this
issue.
2021-06-02 09:22:46 +07:00
Thanabodee Charoenpiriyakij 92009f291c
Upgrade OTP 21,22,23 2021-06-01 21:25:10 +07:00
Thanabodee Charoenpiriyakij 933a678c1b
Use include with specific rebar3 version with OTP 21, upgrade OTP 24
rebar3 v3.16.1 ship support OTP 22+, this cause ci fail on OTP 21. Fixes
by using rebar3 v3.15.2 with OTP 21 and add it with include matrix
instead.

In this changes, upgrade OTP 24 from 24.0.1 to 24.0.2 and change
setup-elixir to setup-beam instead.
2021-06-01 21:17:24 +07:00
Thanabodee Charoenpiriyakij d0bfa1b328
Upgrade Elixir and OTP in GitHub Workflow
This change do:

* Add Elixir 1.12.1 and upgrade 1.11 to latest release.
* Add OTP 24.0.1 and upgrade major OTP release to latest release.
2021-05-31 20:46:30 +07:00
Tristan Sloughter f14066ec4a
Merge pull request #252 from tsloughter/update-docs-button
add github action for sending updated docs to otel.io repo
2021-05-23 12:34:11 -06:00
Tristan Sloughter b37f3c4c68
add github action for sending updated docs to otel.io repo 2021-05-23 09:45:10 -06:00
Fred Hebert 058e431146
Merge pull request #250 from mxiamxia/rm-legacy-port
Remove the OTLP receiver legacy gRPC port(55680) references
2021-05-21 17:22:03 -04:00
xiami 94f5c34a85 Remove all the collector OTLP receiver legacy gRPC port references 2021-05-21 12:20:59 -07:00
Bryan Naegele 7ba7c5cd56 Make pattern match consistent, add tests, and set message on error 2021-05-13 09:14:47 -06:00
Bryan Naegele c9769d6efe Better comply with status compliance 2021-05-12 17:51:16 -06:00
Tristan Sloughter a3d84a72ba
Merge pull request #243 from tsloughter/website_docs-instrumentation
opentelemetry.io: instrumentation docs page
2021-05-08 05:44:05 -06:00
Tristan Sloughter 94b08c6c9c
Merge branch 'main' into website_docs-instrumentation 2021-05-08 05:41:40 -06:00
Tristan Sloughter ac4bae7fbc
Merge pull request #245 from tsloughter/rc2-ready
couple things I caught while starting to publish RC2
2021-05-04 09:40:36 -06:00
Tristan Sloughter f62343d10e
SDK: bump dependency on API to rc.2 2021-05-04 09:18:38 -06:00
Tristan Sloughter 0dc1c6cd00
add Ctx.t type to elixir api 2021-05-04 09:18:01 -06:00
Tristan Sloughter 9274cdba65
Merge pull request #244 from tsloughter/rc2
API: bump RC version to 1.0.0-rc.2
2021-05-04 09:00:51 -06:00
Tristan Sloughter 38f4564df1
API: bump RC version to 1.0.0-rc.2 2021-05-03 17:41:58 -06:00
Tristan Sloughter a94c96e1a6
Merge branch 'main' into website_docs-instrumentation 2021-04-24 16:43:03 -06:00
Tristan Sloughter b834b6156e
instrumentation.md: fix elixir link example by setting parent var 2021-04-24 06:03:50 -06:00
Tristan Sloughter 81ffffc553
Update website_docs/instrumentation.md
Co-authored-by: Łukasz Jan Niemier <lukasz@niemier.pl>
2021-04-24 05:59:44 -06:00
Tristan Sloughter d1566f4206
instrumentation.md: add missing links 2021-04-23 10:17:39 -06:00
Tristan Sloughter c5cb7c1c54
Update website_docs/instrumentation.md
Co-authored-by: Fred Hebert <mononcqc@ferd.ca>
2021-04-23 10:16:04 -06:00
Tristan Sloughter c3ef9aabf4
Merge pull request #242 from tsloughter/auto-tracers
add auto registration of all loaded applications as tracers
2021-04-23 07:53:31 -06:00
Tristan Sloughter fd416b0911
opentelemetry.io: instrumentation docs page 2021-04-23 07:52:55 -06:00
Tristan Sloughter d1b656b486
add auto registration of all loaded applications as tracers 2021-04-23 06:16:56 -06:00
Tristan Sloughter 49f0dd2294
Merge pull request #240 from tsloughter/website-rc
opentelemetry.io: update getting started guide to use 1.0.0-rc1
2021-04-15 07:00:46 -06:00
Tristan Sloughter e39f24c611
opentelemetry.io: update getting started guide to use 1.0.0-rc1 2021-04-14 10:11:31 -06:00
Tristan Sloughter 2c3cb08f59
Merge pull request #239 from tsloughter/exporter-bump-sdk-api-1.0-rc1
bump exporter deps to 1.0.0-rc.1
2021-04-05 14:55:19 -06:00
Tristan Sloughter 672ae5e96e
Merge pull request #238 from tsloughter/sdk-bump-api-1.0-rc1
bump api dep to 1.0.0-rc.1
2021-04-05 11:57:23 -06:00
Tristan Sloughter 815060f501
bump exporter deps to 1.0.0-rc.1 2021-04-05 11:43:06 -06:00
Tristan Sloughter 3f34aa89bb
bump the api dep in sdk app to 1.0.0-rc.1 2021-04-05 11:42:53 -06:00
Tristan Sloughter a9fb88a276
Merge pull request #233 from tsloughter/baggage-encoding
url encode baggage keys and values
2021-04-04 11:44:01 -06:00
Tristan Sloughter 84615da9a9
fix typespec of baggage set function 2021-04-04 11:07:02 -06:00
Tristan Sloughter 89cb2987a1
fix typespec of baggage set function 2021-04-04 11:05:39 -06:00
Tristan Sloughter 7083731424
fix elixir baggage tests 2021-04-04 11:05:39 -06:00
Tristan Sloughter a92f48867a
convert charlist strings to binaries when adding baggage 2021-04-04 11:05:39 -06:00
Tristan Sloughter f2269d4765
add to metadata test case with k/v property 2021-04-04 11:05:39 -06:00
Tristan Sloughter f36b846d8c
support baggage value metadata 2021-04-04 11:05:39 -06:00
Tristan Sloughter a30a792d68
add new api functions to the elixir module 2021-04-04 11:05:38 -06:00
Tristan Sloughter 2650265f60
vendor in percent_decode so OTP 21 and 22 are supported 2021-04-04 11:05:38 -06:00
Tristan Sloughter 66c1cb639f
add optional explicit context argument to baggage functions 2021-04-04 11:05:38 -06:00
Tristan Sloughter f9b4bfa1bb
remove gitter badge, we are on CNCF slack now 2021-04-04 11:05:38 -06:00
Tristan Sloughter 830ab880d4
url encode baggage keys and values 2021-04-04 11:05:38 -06:00
Fred Hebert 346341500b
Merge pull request #237 from austinlparker/addWebsiteDocs
Add opentelemetry.io docs
2021-03-29 13:32:26 -04:00
Austin Parker 186552f58d unignore index file 2021-03-29 12:41:25 -04:00
Austin Parker e1783abef5 add website docs 2021-03-29 12:39:42 -04:00
Fred Hebert 2d5dc8aeac
Merge pull request #230 from garthk/chore/finish-renaming-reporters-to-exporters
Finish renaming reporters to exporters.
2021-03-24 09:00:50 -04:00
Fred Hebert 67beb0030c
Merge branch 'main' into chore/finish-renaming-reporters-to-exporters 2021-03-24 08:53:41 -04:00
Fred Hebert ff182a73dd
Merge pull request #228 from garthk/feat/permit-keyword-list-start-opts
Permit keyword list start_opts in Tracer macros.
2021-03-24 08:52:57 -04:00
Fred Hebert 32e85efd4e
Merge branch 'main' into feat/permit-keyword-list-start-opts 2021-03-24 08:45:26 -04:00
Tristan Sloughter 4889edaf70
Merge pull request #232 from garthk/fix/processor-config-crash
Fix bug preventing configuring span processors
2021-03-24 06:09:36 -06:00
Garth Kidd 8847e1a0ed Fix bug preventing configuring span processors. 2021-03-24 17:10:38 +11:00
Garth Kidd 1193dd5a52 Finish renaming reporters to exporters.
Closes #217.
2021-03-24 09:46:51 +11:00
Garth Kidd f9ab9b94b4 Permit keyword list start_opts in Tracer macros.
Ergonomic for Elixir developers.

Also:

* Repair test name to reflect test code

* Provide tested examples of `with_span/3` with `start_opts` expressed
  as both a map and keyword list
2021-03-24 09:40:22 +11:00
Tristan Sloughter 7a7eb9bfe2
Merge pull request #226 from tsloughter/grpcbox-errors
upgrade grpcbox and log errors returned during export
2021-03-23 05:25:20 -06:00
Tristan Sloughter 2054f75cb5
Merge branch 'main' into grpcbox-errors 2021-03-23 05:19:17 -06:00
Fred Hebert ac9b61282c
Merge pull request #227 from garthk/chore/upgrade-dev-deps
Upgrade dev dependencies past retired version.
2021-03-22 19:34:36 -04:00
Garth Kidd 1fba7b0a43 Upgrade dev dependencies past retired version.
Prompted by:

```plain
$ mix deps.get
...
  elixir_make 0.6.1 RETIRED!
    (invalid) Wrong permissions on the mix.exs file
```

Resolution:

```plain
$ mix deps.update --all
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  covertool 2.0.3
  erlex 0.2.6
  ex_doc 0.21.0
  makeup 1.0.5
  nimble_parsec 1.1.0
Upgraded:
  cmark 0.9.0 => 0.10.0 (minor)
  dialyxir 1.0.0 => 1.1.0
  earmark 1.4.10 => 1.4.14
  earmark_parser 1.4.10 => 1.4.12
  elixir_make 0.6.1 => 0.6.2
  makeup_elixir 0.15.0 => 0.15.1
```
2021-03-23 08:26:06 +11:00
Tristan Sloughter 7060ccca74
upgrade grpcbox and log errors returned during export 2021-03-22 14:01:09 -06:00
Tristan Sloughter 9f0d961f1e
Merge pull request #221 from tsloughter/exporter-config-merging
fix tracer configuration merging
2021-03-16 13:58:29 -06:00
Tristan Sloughter dd2620c942
move back to otlp for default exporter but give a useful warning log if it fails 2021-03-11 08:50:26 -07:00
Tristan Sloughter 19c398c561
use ubuntu-18.04 so setup-elixir action works 2021-03-11 07:24:32 -07:00
Tristan Sloughter 9907c0cc8a
fix tracer configuration merging 2021-03-11 07:24:32 -07:00
Tristan Sloughter ff12ebbaf2
Merge pull request #215 from tsloughter/experimental-metrics
1.0.0-rc.1 - split metrics out to experimental applications
2021-03-11 07:24:16 -07:00
Tristan Sloughter a9493f2d0d
split metrics out to experimental applications 2021-03-04 11:35:21 -07:00
Tristan Sloughter b3336e210e
Merge pull request #213 from tsloughter/exporter-path
support path on traces endpoints
2021-02-23 16:54:24 -07:00
Tristan Sloughter 995cf3952a
support path on traces endpoints 2021-02-22 19:10:21 -07:00
Tristan Sloughter b4c2df59b3
Merge pull request #212 from tsloughter/api-cleanup
endpoint parsing exporter fixes and small cleanup in tracer
2021-02-22 13:29:07 -07:00
Tristan Sloughter 3db36a3dda
fix ctx token type spec 2021-02-22 10:17:57 -07:00
Tristan Sloughter bf4a5a4c4e
add test of parsing a bad uri for endpoint 2021-02-21 09:17:55 -07:00
Tristan Sloughter 7dc54caa88
add Erlang macro with_span/2 to match Elixir API 2021-02-21 09:12:26 -07:00
Tristan Sloughter fd84bf42e5
use ctx detach at end of with_span 2021-02-21 09:11:55 -07:00
Tristan Sloughter 005025442a
fix exporter endpoints parsing for binaries 2021-02-21 09:09:49 -07:00
Tristan Sloughter 4b38bb42ab
Merge pull request #211 from tsloughter/unknown-types
fix unknown type spec references
2021-02-19 07:37:45 -07:00
Tristan Sloughter d355bc5e05
Update apps/opentelemetry/src/otel_metric_aggregator_mmsc.erl
Co-authored-by: Bryan Naegele <bryannaegele@users.noreply.github.com>
2021-02-19 07:30:03 -07:00
Tristan Sloughter d0d77ca5af
fix unknown type spec references 2021-02-18 16:17:58 -07:00
Tristan Sloughter 03654e5ef4
Merge pull request #210 from tsloughter/exporter-load-comment
add load of exporter app in configuration and comment on why
2021-02-18 16:17:45 -07:00
Tristan Sloughter 04099b7745
add load of exporter app in configuration and comment on why 2021-02-18 06:28:53 -07:00
Tristan Sloughter fc4269027d
Merge pull request #208 from tsloughter/process-resource-attributes
add service.name fallback and process resource attributes
2021-02-17 11:56:23 -07:00
Tristan Sloughter f1ce99cd5f
Merge branch 'main' into process-resource-attributes 2021-02-17 11:52:10 -07:00
Tristan Sloughter 2b75733982
fix test to use RELEASE_VSN for environment variable 2021-02-17 11:45:01 -07:00
Tristan Sloughter 0c10feda4a
Merge pull request #207 from tsloughter/config-exporter
support OS environment variables for setting tracer to OTLP
2021-02-17 11:24:46 -07:00
Tristan Sloughter 3aca2d6051
use RELEASE_PROG to get executable name if available 2021-02-17 09:37:13 -07:00
Tristan Sloughter 00e794b7b4
set traces exporter to none in tests 2021-02-17 08:08:09 -07:00
Tristan Sloughter dc063453b4
set traces exporter to none in tests 2021-02-17 08:05:20 -07:00
Tristan Sloughter 6108fae683
load exporter in elixir tests 2021-02-17 08:02:22 -07:00
Tristan Sloughter edd7580f65
load exporter in elixir tests 2021-02-17 08:01:56 -07:00
Tristan Sloughter 8ce61bd26f
add service.name fallback and process resource attributes 2021-02-16 18:38:26 -07:00
Tristan Sloughter 1de408428a
support OS environment variables for setting tracer to OTLP 2021-02-16 13:03:37 -07:00
Tristan Sloughter 441d2af9cc
Merge pull request #206 from tsloughter/exporter-headers
exporter: support for endpoint and header configuration
2021-02-16 11:52:49 -07:00
Tristan Sloughter 62e5ba356b
exporter: support for endpoint and header configuration 2021-02-16 08:48:22 -07:00
Tristan Sloughter abf1e6bc32
Merge pull request #205 from gugahoa/fix-set-current-span-spec
Fix `set_current_span` spec
2021-02-15 08:45:59 -07:00
Gustavo Aguiar 266825884c Fix `set_current_span` spec
This function also accepts `undefined` as argument
2021-02-14 23:46:59 -03:00
Tristan Sloughter 0cf62700c5
Merge pull request #203 from pallix/bump-lib-version-in-README
Update version in README for the api bump to 0.6.0
2021-02-12 11:47:06 -07:00
Pierre Allix e98958c4de Update version in README for the api bump to 0.6.0 2021-02-12 12:16:02 +01:00
Tristan Sloughter 00261d5b7e
Merge pull request #201 from tsloughter/0.6.0
bump api VERSION to 0.6.0
2021-02-11 18:15:03 -07:00
Tristan Sloughter 5caee82bd3
bump api VERSION to 0.6.0 2021-02-11 16:25:08 -07:00
Tristan Sloughter 3d26b62d4f
Merge pull request #138 from gugahoa/add-record-exception
Add RecordException to Elixir's Span module
2021-02-11 16:24:25 -07:00
Tristan Sloughter 37f555941b
Apply suggestions from code review 2021-02-11 16:21:33 -07:00
Gustavo Aguiar 7856ba8270 fixup! Add `record_exception` to Erlang 2021-02-11 17:46:58 -03:00
Gustavo Aguiar 60db22bd3a fixup! Add `record_exception` to Erlang 2021-02-11 17:42:57 -03:00
Tristan Sloughter 1e22090876
Merge branch 'main' into add-record-exception 2021-02-11 12:42:48 -07:00
Tristan Sloughter 3995f77e39
Merge pull request #193 from tsloughter/exporter-fail
handle grpcbox failure in exporter and fallback to http
2021-02-11 12:40:40 -07:00
Tristan Sloughter b6d30e53f9
Merge branch 'main' into exporter-fail 2021-02-11 12:38:13 -07:00
Tristan Sloughter e24e23a2c9
Merge branch 'main' into add-record-exception 2021-02-11 12:38:08 -07:00
Tristan Sloughter 3186a3cec0
Merge pull request #188 from tsloughter/rationale
add rationale document with versioning/releasing details
2021-02-11 12:37:25 -07:00
Tristan Sloughter 48b5fdfd5f
removing versioning rationale doc to VERSIONING file 2021-02-11 12:34:00 -07:00
Tristan Sloughter 59251466ca
Apply suggestions from code review
Co-authored-by: Greg Mefford <greg@gregmefford.com>
2021-02-11 12:33:14 -07:00
Tristan Sloughter 4d621d27e0
Update docs/rationale.md
Co-authored-by: Greg Mefford <greg@gregmefford.com>
2021-02-11 12:33:14 -07:00
Tristan Sloughter 288037ccd3
fix formatting of first paragraph 2021-02-11 12:33:14 -07:00
Tristan Sloughter 1d829bac0b
Update docs/rationale.md
Co-authored-by: Garth Kidd <garth@garthk.com>
2021-02-11 12:33:13 -07:00
Tristan Sloughter 7404f19e9e
Update docs/rationale.md
Co-authored-by: Garth Kidd <garth@garthk.com>
2021-02-11 12:33:13 -07:00
Tristan Sloughter 501b520d3f
add rationale document with versioning/releasing details 2021-02-11 12:33:13 -07:00
Tristan Sloughter d1cb5715e5
upgrade grpcbox to 0.13.1 2021-02-10 18:18:52 -07:00
Tristan Sloughter a62d0b34e0
handle grpcbox failure in exporter and fallback to http 2021-02-10 18:17:50 -07:00
Tristan Sloughter aafabf3474
Merge pull request #200 from tsloughter/up-grpc-protos
update the otel protos and grpcbox
2021-02-06 15:00:42 -07:00
Tristan Sloughter 4652f770c0
upgrade otel protos 2021-02-06 11:27:06 -07:00
Tristan Sloughter 0a94a76fe4
upgrade grpcbox to 0.13.0 2021-02-06 11:26:46 -07:00
Tristan Sloughter 2d000dded5
Merge pull request #199 from tsloughter/with-span-type-spec
otel_tracer: fix with_span/5 type spec
2021-02-02 14:18:58 -07:00
Tristan Sloughter 3213ba6750
otel_tracer: fix with_span/5 type spec 2021-02-02 11:08:44 -07:00
Tristan Sloughter 613f2d1086
Merge pull request #198 from tsloughter/exporter-encode-links
exporter: fix trace_state encoding in links
2021-02-02 08:34:53 -07:00
Tristan Sloughter 520ab8909e
exporter: fix trace_state encoding in links 2021-02-02 08:06:45 -07:00
Tristan Sloughter fc25e7a7ad
switch default branch to 'main' 2021-02-01 12:51:14 -07:00
Tristan Sloughter 529039d14d
Merge pull request #197 from tsloughter/fix-link-tracestate
support an undefined TraceState when creating a link
2021-02-01 12:42:18 -07:00
Tristan Sloughter 1580d77b10
detach new context in elixir tests 2021-02-01 12:33:34 -07:00
Tristan Sloughter a42668d84d
end parent spans in elixir tests 2021-02-01 06:34:05 -07:00
Tristan Sloughter aa817764d0
support an undefined TraceState when creating a link 2021-02-01 06:19:17 -07:00
Fred Hebert 580d70e6e2
Merge pull request #196 from open-telemetry/chore/change-employer
Employer change
2021-01-29 15:24:28 -05:00
Fred Hebert 54178e3a37
Employer change 2021-01-29 15:20:15 -05:00
Tristan Sloughter 101879d8da
Merge pull request #194 from tsloughter/env-vars-1
add configuration module to merge OS env with app env
2021-01-25 16:44:30 -07:00
Tristan Sloughter 31aad588fc
add configuration module to merge OS env with app env 2021-01-23 14:16:09 -07:00
Łukasz Jan Niemier 8161404bb5
Merge pull request #192 from open-telemetry/chore/change-employer
Change of the employer
2021-01-13 17:23:20 +01:00
Łukasz Jan Niemier 6d0ae662b4
chore: change Tristan employer
Co-authored-by: Tristan Sloughter <t@crashfast.com>
2021-01-13 17:21:10 +01:00
Łukasz Jan Niemier 704a8909df
chore: change of the employer 2021-01-13 17:10:14 +01:00
Gustavo Aguiar b9f9be7a05 fixup! Add RecordException to Elixir's Span module 2020-12-23 16:58:40 -03:00
Gustavo Aguiar 6756f9f695 fixup! fixup! fixup! Add `record_exception` to Erlang 2020-12-23 12:17:59 -03:00
Gustavo Aguiar 1f2893f37c fixup! fixup! Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar 7157516e5c fixup! Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar cc4c82e62e fixup! Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar ac47237623 fixup! Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar dd078fd8e5 fixup! Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar 1f1410bd8c fixup! Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar 0aea6d37e3 Add `record_exception` to Erlang 2020-12-23 12:02:48 -03:00
Gustavo Aguiar f8f78acbf8 Add RecordException to Elixir's Span module
Reference for [`RecordException`](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md#record-exception)

`RecordException` has been implemented only on Elixir side as it has a
more uniform way to deal with exceptions as a value.

The attribute `exception.escaped` is left up to the user to supply
through the `attributes` parameter in `record_exception/4`.
2020-12-23 12:02:43 -03:00
Tristan Sloughter 91570688ac
Merge pull request #175 from chulkilee/lowercase-atom
Lowercase atom
2020-12-18 10:38:39 -07:00
Tristan Sloughter a389ac9ef3
Merge branch 'master' into lowercase-atom 2020-12-18 10:32:50 -07:00
Tristan Sloughter d52bc5c636
Merge pull request #190 from tsloughter/detectors
add resource detection behaviour and configuration
2020-12-18 08:16:18 -07:00
Tristan Sloughter fb6aacbbc6
move resource detection to processes run by gen_statem 2020-12-16 09:06:45 -07:00
Tristan Sloughter 307c4faeaa
add resource detection behaviour and configuration 2020-12-13 14:36:38 -07:00
Chulki Lee 4b4e90b5b5 use lowercase for span kind 2020-12-12 10:16:11 +09:00
Chulki Lee e55a2c4542 use lowercase for span status 2020-12-12 10:16:11 +09:00
Tristan Sloughter dfa2918931
Merge pull request #183 from tsloughter/expand-elixir-tracer
expand Elixir trace API
2020-12-08 16:40:21 -07:00
Tristan Sloughter 1372b6569d
clear github actions caches 2020-12-07 07:53:18 -07:00
Tristan Sloughter 49de8c775c
expand Elixir trace API
start_span, no matter the arity, always returns only a span_ctx now

the Tracer module includes macros that accept Context variables
instead of reading the context from the pdict, allowing explicit
parent spans to be used again.
2020-12-07 07:45:57 -07:00
Tristan Sloughter ea02818322
Merge pull request #172 from tsloughter/api-repo-readme
remove reference to opentelemetry-erlang-api in the README
2020-11-29 13:01:06 -07:00
Tristan Sloughter 2411809b3c
Update README.md
Co-authored-by: Peter Saxton <peterhsaxton@gmail.com>
2020-11-29 11:48:49 -07:00
Tristan Sloughter 366daa8c82
Merge branch 'master' into api-repo-readme 2020-11-29 11:33:15 -07:00
Tristan Sloughter be828b2a79
Merge pull request #177 from chulkilee/elixir-format
use elixir formatter
2020-11-29 09:08:30 -07:00
Chulki Lee e44f7cd407 use elixir formatter 2020-11-29 16:16:50 +09:00
Tristan Sloughter ecaf56597f
remove reference to opentelemetry-erlang-api in the README 2020-11-28 10:31:11 -07:00
Tristan Sloughter e91eb24d0d
Merge pull request #161 from tsloughter/counter-bind-test
add test of bound counter
2020-11-28 06:54:39 -07:00
Tristan Sloughter d102c03610
Merge branch 'master' into counter-bind-test 2020-11-28 06:51:58 -07:00
Tristan Sloughter 9de8af27ce
Merge pull request #159 from robashton/missing-mappings
Fill out aggregator/instrument kind mapping
2020-11-27 09:21:25 -07:00
Tristan Sloughter a7868bc1d7
Merge branch 'master' into missing-mappings 2020-11-27 08:32:48 -07:00
Tristan Sloughter 3006070dea
Merge pull request #158 from robashton/observer-specs
Line up observe callback specs
2020-11-27 08:32:31 -07:00
Tristan Sloughter 2e4119bd68
Merge branch 'master' into observer-specs 2020-11-27 08:29:39 -07:00
Tristan Sloughter ea89846599
add test of bound counter 2020-11-27 08:28:25 -07:00
Tristan Sloughter 611d239d48
Merge pull request #157 from robashton/fix-bind
bind needs to return {{key, labels}, instrument}
2020-11-27 08:26:58 -07:00
Tristan Sloughter 66005540b3
Merge branch 'master' into fix-bind 2020-11-26 10:42:33 -07:00
Tristan Sloughter aaf32267d1
Merge branch 'master' into missing-mappings 2020-11-26 10:24:46 -07:00
Tristan Sloughter b421c17484
Merge branch 'master' into observer-specs 2020-11-26 10:23:58 -07:00
Nicholas Wolverson 6900d1e1bd Fill out aggregator/instrument kind mapping 2020-11-26 17:07:22 +00:00
Nicholas Wolverson b9139babff Line up observe callback specs 2020-11-26 17:06:34 +00:00
robashton 6f8c9dbd27 bind needs to return {{key, labels}, instrument} 2020-11-26 17:03:36 +00:00
Tristan Sloughter fcba453fb6
Merge pull request #153 from tsloughter/no-api-start-span
pass parent span context along when no sdk is used
2020-11-25 07:32:05 -07:00
Tristan Sloughter b5c08ff211
match noop tracer with api spec for starting spans 2020-11-23 08:34:16 -07:00
Tristan Sloughter 29a66ffab6
make default sample flag in span ctx 0 2020-11-23 08:33:48 -07:00
Tristan Sloughter a13d0b595f
Merge pull request #152 from tsloughter/final-fixups-0.5.0
Final fixups for 0.5.0
2020-11-21 06:55:36 -07:00
Tristan Sloughter b3148c7256
add doc dir to gitignore 2020-11-20 09:07:33 -07:00
Tristan Sloughter 84b479af70
add pr2relnotes.sh for generating changelogs for releases 2020-11-20 09:06:56 -07:00
Tristan Sloughter 501f55fd9e
exporter: fix github link 2020-11-20 09:06:31 -07:00
Tristan Sloughter cb74034658
api: fix github link in hex package 2020-11-20 08:29:43 -07:00
Tristan Sloughter 482e8e6f82
Merge pull request #151 from tsloughter/mv-license-apps
copy license to all sub-apps for including in hex packages
2020-11-20 08:25:23 -07:00
Tristan Sloughter 120c9093de
copy license to all sub-apps for including in packages 2020-11-20 08:17:50 -07:00
Tristan Sloughter 70737530b9
Merge pull request #150 from tsloughter/exdoc-edoc-fixes
exdoc and edoc fixes
2020-11-20 08:09:11 -07:00
Tristan Sloughter 269dcd1784
pin ex_doc to 0.21.0 where cmark is supported
cmark is required so rendering of edown generated markdown
docs works properly. The HTML is screwed up when using
the default ex_doc markdown renderer.
2020-11-20 07:54:48 -07:00
Tristan Sloughter cc99586cda
fix edoc quoting in otel_ctx module header docs 2020-11-20 07:53:29 -07:00
Tristan Sloughter 1891eabf8b
Merge pull request #148 from tsloughter/api-bump-0.5.0
Bump API to 0.5.0 and fix otel_instrument to work with edoc
2020-11-20 07:48:58 -07:00
Tristan Sloughter 601ae8a51f
bump API version to 0.5.0 2020-11-20 07:09:48 -07:00
Tristan Sloughter ceedf80847
api: remove doc tags from otel_instrument that aren't allowed by edoc 2020-11-20 07:09:38 -07:00
Tristan Sloughter b9581a1cc8
Merge pull request #146 from tsloughter/add-rebar-dep
Add rebar dep
2020-11-16 09:53:02 -07:00
Tristan Sloughter 2e9c432520
add SDK and API deps to the exporter rebar.config 2020-11-16 08:57:27 -07:00
Tristan Sloughter be90b94b6e
fix api dep in top level mix.exs used for tests 2020-11-16 08:51:08 -07:00
Tristan Sloughter c39bf9fcd9
update readme to use override for API dep 2020-11-16 08:36:27 -07:00
Tristan Sloughter d84475d6fa
add opentelemetry_api to rebar.config of sdk app 2020-11-16 08:30:43 -07:00
Tristan Sloughter b5e6b65edd
Merge pull request #145 from tsloughter/fix-add-event
fix add_event macro to call otel_span:add_event/3
2020-11-14 20:00:45 -07:00
Tristan Sloughter e9576bc0d9
fix add_event macro to call otel_span:add_event/3 2020-11-14 11:23:44 -07:00
Tristan Sloughter 1d5a5a0549
Merge pull request #143 from tsloughter/move-propagators-api
move propagators to the api
2020-11-14 11:23:36 -07:00
Tristan Sloughter f12ecf73c0
move propagators to the api 2020-11-08 10:06:25 -07:00
Tristan Sloughter 0e448fd368
Merge pull request #139 from tsloughter/update-protos
update protos
2020-11-07 08:27:02 -07:00
Tristan Sloughter fb94a129fa
update status code to latest spec and remove http status mapping 2020-11-06 09:46:01 -07:00
Tristan Sloughter fd2a647c34
update set of status codes for span 2020-11-06 09:21:03 -07:00
Tristan Sloughter 64c18d2b82
update protos 2020-11-05 17:01:30 -07:00
Tristan Sloughter bcd54678ef
Merge pull request #137 from open-telemetry/is-recording-behaviour
set is_recording to false when span is ended
2020-11-03 08:29:42 -07:00
Tristan Sloughter 174f189b37
only check that module exists since behaviour could be stripped 2020-11-03 08:13:39 -07:00
Tristan Sloughter e15d64db14
set is_recording to false on span context when ending 2020-11-03 08:13:39 -07:00
Tristan Sloughter a3f9fa77a1
Merge pull request #134 from open-telemetry/sampler-ctx-drop
update sampler to take a context and update some names to match spec
2020-11-02 08:16:57 -07:00
Tristan Sloughter 54f629ea05
add explicit test of custom sampler module 2020-10-31 18:22:14 -06:00
Tristan Sloughter 74a50ae2eb
update sampler to take a context and update some names to match spec 2020-10-31 17:39:59 -06:00
Tristan Sloughter ee1fc15f31
Merge pull request #133 from davydog187/resource-attributes
OTEL_RESOURCE_(LABELS -> ATTRIBUTES)
2020-10-30 15:46:20 -06:00
Dave Lucia 859033fd89 OTEL_RESOURCE_(LABELS -> ATTRIBUTES)
Ran into an issue getting Lightstep running locally, and realized it was
due to a name change on the `OTEL_RESOURCE_LABELS` env variable. It
recently changed in the spec.

https://github.com/open-telemetry/opentelemetry-specification/pull/758
c9eeaaec21/specification/sdk-environment-variables.md
2020-10-30 14:36:28 -04:00
Tristan Sloughter 8a99f12dbd
Merge pull request #131 from tsloughter/test-default-sampler
set and test the default sampler
2020-10-29 12:40:23 -06:00
Tristan Sloughter 7c994283b5
add tests of default sampler 2020-10-29 09:34:04 -06:00
Tristan Sloughter 79a36e7622
remove unused sampler include from otel_batch_processor_SUITE 2020-10-29 09:34:04 -06:00
Tristan Sloughter 8099e48058
set default sampler to ParentBased with root AlwaysOn 2020-10-29 09:34:04 -06:00
Tristan Sloughter 6da493fc4d
Merge pull request #129 from tsloughter/sampler-descriptions
add get_description to sampler and support for updating tracestate in sampler
2020-10-29 09:05:17 -06:00
Tristan Sloughter 799d2410f8
add complete parent_based sampler description 2020-10-29 08:50:11 -06:00
Tristan Sloughter 4db86fad9e
add get_description to sampler exported functions 2020-10-28 09:10:09 -06:00
Tristan Sloughter 15cba94e1d
Merge pull request #127 from tsloughter/ratio-parent-based
update samplers to latest spec: parent_based & trace_id_ratio_based
2020-10-28 09:10:00 -06:00
Tristan Sloughter d7a0e3dfbc
update samplers to latest spec: parent_based & trace_id_ratio_based 2020-10-27 17:53:41 -06:00
Tristan Sloughter 3d12c51807
Merge pull request #126 from tsloughter/span-ops
remove Tracer argument when not used and add span ops to otel_span
2020-10-27 08:06:13 -06:00
Tristan Sloughter 44f98fdd05
Tracer.set_current_span doesn't need to be a macro 2020-10-26 09:24:28 -06:00
Tristan Sloughter 4646d2092e
remove Tracer argument when not used and add span ops to otel_span
also added a top level mix.exs and fake app to run elixir tests
that use the api and sdk.
2020-10-25 18:40:15 -06:00
Tristan Sloughter 4c54edf9fb
Merge pull request #121 from tsloughter/elixir-ctx-module
add Elixir modules for baggage and context
2020-10-15 09:55:53 -06:00
Tristan Sloughter 919d552528
Merge branch 'master' into elixir-ctx-module 2020-10-15 09:52:22 -06:00
Tristan Sloughter 5b002cec7e
Merge pull request #115 from tsloughter/ctx-api
remove context modification in start and end_span
2020-10-15 09:52:06 -06:00
Tristan Sloughter 37dfc40fc9
Merge branch 'master' into ctx-api 2020-10-10 13:34:59 -06:00
Tristan Sloughter d118fbd4ce
add Elixir modules for baggage and context 2020-10-10 08:55:37 -06:00
Tristan Sloughter c4988b98e0
Merge pull request #114 from hauleth/ft/import-exporter
Import OTLP exporter
2020-10-06 15:16:35 -06:00
Tristan Sloughter 011e028497
remove context modification in start and end_span
This removes the need for #tracer_ctx and instead only stores
the current span ctx.

Updates to Elixir tracer macros and tests included as well for
using the new Erlang API.
2020-10-01 09:38:44 -06:00
Łukasz Niemier b4b8599318
fix: use better Docker Compose configuration 2020-10-01 02:21:42 +02:00
Łukasz Niemier 0c5efa1fb5
Merge commit '19912c55cbe55e51877d736e24391f8eb1dfcb44' into ft/import-exporter 2020-10-01 01:51:10 +02:00
Tristan Sloughter 19912c55cb
Merge pull request #14 from opentelemetry-beam/v0.5.0-protos
update protos to v0.5.0
2020-09-30 16:46:01 -06:00
Łukasz Niemier a7b1d7e49b
chore: centralise configuration 2020-09-30 22:28:52 +02:00
Łukasz Niemier 5de2b88efd
fix: always send coverage reports 2020-09-30 22:19:21 +02:00
Łukasz Niemier aeec09d131
fix: expand CI pipeline to include Exporter 2020-09-30 22:13:02 +02:00
Łukasz Niemier c21640c990
fix: use new otel_* prefix instead of ot_* 2020-09-30 21:07:17 +02:00
Łukasz Niemier a75a2c83d8
fix: move the grpc_plugin to top rebar.config 2020-09-30 21:06:43 +02:00
Łukasz Niemier 24e50eb3ee
fix: add the opentelemetry-proto submodule 2020-09-30 21:01:44 +02:00
Łukasz Niemier e633e9f0ac Add 'apps/opentelemetry_exporter/' from commit 'd3a684359096ca83181358c1dcd146118bc65de7'
git-subtree-dir: apps/opentelemetry_exporter
git-subtree-mainline: 618ccd452d
git-subtree-split: d3a6843590
2020-09-30 20:48:17 +02:00
Tristan Sloughter 618ccd452d
support user defined text_map propagators (#110)
* http propagator renamed to text_map

propagator behaviour is moved to the api so users can create
propagators and only depend on the api to write them.

* add test of custom propagation implementation

* improve type of the anonymous function stored in extractor/injector
2020-09-29 15:30:01 -06:00
Tristan Sloughter d33a383f41
replace ot_ prefix with otel_ as required by the spec (#109)
* replace ot_ prefix with otel_ as required by the spec

* add otel_ prefix to api header files
2020-09-26 07:28:10 -06:00
Tristan Sloughter d3a6843590
Merge pull request #16 from opentelemetry-beam/handle-tuple-attrs
Add support for tuple attr values
2020-09-25 08:27:53 -06:00
Bryan Naegele b9ae848a91
Update event name specs (#105) 2020-09-25 08:21:57 -06:00
Łukasz Jan Niemier e0b9a0922a
chore: fix labeler (#108) 2020-09-25 14:55:16 +02:00
bryannaegele 40c44eea69 Add support for tuple attr values 2020-09-24 22:32:59 -06:00
Łukasz Jan Niemier 851fdfda62
Run Elixir tests in GitHub Actions (#104)
* chore: run Elixir tests in GitHub Actions

* fix: Dialyzer issues

* fix: better cache for GitHub Actions

* fix: do not run Dialyzer on 21.x

There are problems with persistent_term on that release, so for now just
skip it.
2020-09-25 00:34:11 +02:00
Bryan Naegele 63b0966d2d
Merge pull request #15 from opentelemetry-beam/otel-v0.4
Otel v0.4
2020-09-23 17:33:34 -06:00
bryannaegele aae8d19d87 Otel v0.4 2020-09-23 17:27:37 -06:00
Łukasz Jan Niemier a9091ed2a3
Fix Dialyzer issues (#101)
* Fix dialyzer issues

* Run dialyxir in github actions

* use elixir 1.10.4

* add a cache

* Fix otp version

* fix(ot_meter): typespecs for callback

Co-authored-by: Dave Lucia <davelucianyc@gmail.com>
2020-09-24 01:10:21 +02:00
Łukasz Jan Niemier 02c314957b
chore: automatically label PRs depending on the changes (#103) 2020-09-24 01:02:20 +02:00
Tristan Sloughter dd0e06a03b
Merging continued (#100)
* add note in readme on using git sparse deps

* remove redundant files from api dir
2020-09-23 20:42:25 +02:00
Łukasz Jan Niemier c25ac35360
Merge API and SDK (#99)
* Initial commit

* api initial commit

ot_tracer: behavour that an otel tracer must implement
ot_span: behaviour an otel span must implement
otel: friendly user api on top of ot_tracer and ot_span

* ot_span: add type specs on functions

* add functions for creating records and align with latest otel protos

* update readme to describe use of api application

* updates for fred's PR review

* separate context propagation otep

* add with_value function to run function with scoped context

* add http propagation for baggage, correlation and trace

* remove callbacks from otel module that were accidentally copeid from ot_span

* fix type specs after dialyzing opentelemetry

* fix baggage and correlations to/from http propagation

* add verification checks that tracer and context implement behaviours

* add optional config value to context manager like the tracer

* add some additional type specs

* make propagator funs fully qualified

important for being able to run upgrades. without fully qualified
functions the funs will eventually become badfuns after the
third module reload.

* update span start_opts to include attributes, sampling hint and start_time (#6)

* Initial Elixir API (#3)

* start on the elixir API

* add .gitignore, address feedback

* update span start_opts to include attributes, sampling hint and start_time (#6)

* use VERSION file for application version

* read version from version file

Co-authored-by: Tristan Sloughter <t@crashfast.com>

* remove baggage. it was removed from otep-66 (#9)

* remove resource from span record (#12)

* add CODEOWNERS file (#15)

* Registering named tracers (#16)

* add tracer provider interface for named tracers

* update readme with use about named tracer

* fix register_tracer type spec

* move span record to sdk

* add additional details about what register_tracer does

* new registeration, plus add set_span/2, end_span/2 and replace otel with macros in tracer.hrl (#17)

* support registering an application's tracer

* add set_span/2, end_span/2 and replace otel with macros in tracer.hrl

* update readme to use register_application_tracer/1

* Set Erlang Approvers as CODEOWNERS (#19)

* Elixir API based on the Erlang macro api and application registered tracers (#18)

* add set_span/2, end_span/2 and replace otel with macros in tracer.hrl

* Elixir API macros to match the Erlang macros

* include erlang docs in elixir docs (#20)

* include erlang docs in elixir docs

* make erlang_docs function in mix.exs more readable

* make edocs before mix docs and add hex metadata

* make use of is_recording in ot_span and update events field to latest spec (#21)

* use is_recording to skip possibly expensive span ops

* update Event type to otel beta spec

* missed a couple of is_recording and events changes (#22)

* remove old is_recording_events callback

* fix add_events callback type spec to new events record type

* fixing up mix.lock and use of event (#23)

* update elixir opentelemetry api to replace time events with events

* update mix lock file

* expand the docs in open_telemtry.ex, the readme and add CONTRIBUTING.md (#24)

* add elixir docs to OpenTelemetry module

* add register_application_tracer function to OpenTelemetry module and elixir to readme

* add readme section about including the SDK

* add contributing doc

* add docs to span.ex and tracer.ex

* chore: cleanup Elixir code

- Macros use `:bind_quoted` where possible
- Remove needless aliases in tests

* Add create_span and new end_span/2 (#27)

* Share configuration between Rebar3 and Mix (#11)

* ft: share configuration between Rebar3 and Mix

This should reduce amount of places where the configuration mismatch can
happen. Current solution uses Rebar3 configuration as a source of truth.

TBD:

- support for Rebar3 profile sharing

* fix(docs): build pages for the Erlang files

* chore: update mix.lock

* a bit of cleanup (#29)

* remove unused context with_value function

* fix is_recording macro in tracer header

* opentelemetry metrics API (#7)

* opentelemetry metrics API

This patch includes a behaviour for implementing the Meter SDK and
API modules for calling the meter for creating and recording
measurements.

* Update src/ot_meter.erl

Co-Authored-By: Arkadiusz Gil <arkgil@users.noreply.github.com>

* cleanup of metrics api based on comments on PR

* add Meter Provider

* remove gauge

* add meter macros and registration

* add elixir meter api module

* add register_application_* functions to OpenTelemetry module

* add observer api

* add elixir modules for counter, measure and observer api

* add meter to bound instrument return to simplify api

* updates to observer api

* remove label set function

* more simplification and some docs

* fix meter lookup

* add counter and measure specific macros

* fix get_meter typespec and add miissing callbacks to noop meter

* fix provider return values to booleans for registering traer/meter

Co-authored-by: Arkadiusz Gil <arkgil@users.noreply.github.com>

* take default argument in ot_ctx:ctx and some simple bug fixes (#38)

* Add callbacks for getting the Resource from a tracer provider (#40)

* handle codechange in ot_tracer_provider

* add callback to get resource from tracer provider

* fix spec for provider resource fetching as resource is defined in the SDK

* bump VERSION file to 0.3.0 (#41)

* add include dir to files published to hex (#42)

* removing wts dependency (#43)

* add hex metadata

* remove use of wts. get time_offset at export instead of at creation

* use system time in nano seconds for an event time

* version bump to 0.3.1 (#44)

* add otel exporter to list and add lists for integrations (#45)

* update readme to use set_attribute not the old add_attribute (#50)

* drop attributes and events that aren't a list (#51)

* Repair typespec (#46)

I'm pretty sure you didn't intend to document
[`register_application_tracer/1`][rat1] as:

> Current time in UNIX Epoch time, nanoseconds since 00:00:00 UTC on
> 1 January 1970.

... but that's how it turned out, perhaps due to a slip-up in 54ce3ad.

[rat1]: https://hexdocs.pm/opentelemetry_api/0.3.1/OpenTelemetry.html#register_application_tracer/1

Co-authored-by: Tristan Sloughter <t@crashfast.com>

* fix bug where there is no current span ctx and update_name is called (#52)

* replace create_span with start_inactive_span (#53)

* Add accessors to deconstruct Span (#54)

* Add accessors to deconstruct Span

When trying to link traces across separate systems (either linked via
HTTP calls or a message queue), having direct access to the TraceID and the
SpanID make it easier to serialize this properly and recreate a Link on
the receiving end.

This PR adds support for deconstructing a Span Context to get access to
these values.

I've added a couple of tests but they aren't all passing, so could use a
hand getting the test for establishing links to parent trace in shape.

* Rework CT test

* Use the right type on type specs

* Removed test that should be part of an SDK instead

* Fix issues/48 (#56)

- OpenTelemetry removing `/"` and  replacing this with
`"` as it creates confusion.
- Updated the example doc for the new API updates.

Modified `OpenTelemetry.Span`
Following changes were done.

- Changes related to documentation example `add_event`
- Updated `add_event/1` to `add_event/2` to accept
`event_name` and `event_attributes`.

* Update readme (#59)

* version bump to 0.3.2 (#55)

* Fixing the string formatting acrosst the project. (#62)

Changes to be committed:
	modified:   lib/open_telemetry/measure.ex
	modified:   lib/open_telemetry/meter.ex
	modified:   lib/open_telemetry/observer.ex
	modified:   lib/open_telemetry/tracer.ex

* Update span add_event docs variable name (#64)

Seems like the variables on lines 9,10 (`ecto_attributes`, and `ecto_event`) are the same variable, but named differently?

* Unspecified is not a valid span kind (#67)

* move context implementation to api app (#66)

* moving to github actions to use the same as the rest of OpenTelemetry org (#68)

* fix sampler typespec to term() since sampler is in SDK app

* move to github actions for CI

* support passing just a span_ctx to link functions (#69)

* support passing just a span_ctx to link functions

* use covertool and codecov instead of coveralls

* fix elixir otp version in main.yml

* fix link/2 to take undefined atom and fix typespecs

* correct docs for timestamp functions (#70)

* Add http status helper (#78)

* Add http status helper

* Update module doc

* Fix message fallback

* Use macro

* Update headers typing (#79)

Co-authored-by: Tristan Sloughter <t@crashfast.com>

* Add atom support (#80)

* Remove CircleCI (#81)

Github actions appears to be the CI system now

* Metrics api 0.4.0 (#71)

* remove uses of 'labelset' which was removed from the spec

* initial work on updated metrics api 0.4.0

* rename instrument function to definition and add elixir api

* prefix meter macros with ot_

* Update lib/open_telemetry/sum_observer.ex

Co-authored-by: Tino Breddin <tolbrino@users.noreply.github.com>

* Update lib/open_telemetry/updown_sum_observer.ex

Co-authored-by: Tino Breddin <tolbrino@users.noreply.github.com>

* add some docs to ot_instrument

Co-authored-by: Tino Breddin <tolbrino@users.noreply.github.com>

* ctx api update and add optional explicit ctx argument to start span functions (#83)

* rename correlations to baggage

* update context api

* make context to an optional explicit argument to start_span

* rename ot_ctx:ctx() type to ot_ctx:t() to be consistent

* feat: move opentelemetry app under apps

* fix: remove CircleCI configuration

* fix(cover): upload coverage report for API

* fix: run CT in CI as well as EUnit

* chore(cover): properly mark each coverage report

This should result with better reports as soon as coverage reports start
to parse.

Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>
Co-authored-by: Tristan Sloughter <t@crashfast.com>
Co-authored-by: Zach Daniel <zachary.s.daniel@gmail.com>
Co-authored-by: Greg Mefford <greg@gregmefford.com>
Co-authored-by: Arkadiusz Gil <arkgil@users.noreply.github.com>
Co-authored-by: Garth Kidd <garth@garthk.com>
Co-authored-by: Leandro Ostera <leandro@ostera.io>
Co-authored-by: Yatender Singh <yatender.nitk@gmail.com>
Co-authored-by: Marc Delagrammatikas <delagrammatikas@gmail.com>
Co-authored-by: Bryan Naegele <bryannaegele@users.noreply.github.com>
Co-authored-by: Dave Lucia <davelucianyc@gmail.com>
Co-authored-by: Tino Breddin <tolbrino@users.noreply.github.com>
2020-09-23 06:49:30 -06:00
Tristan Sloughter 48f1769837
take only a context and not a span ctx or span for parent (#97)
* take only a context and not a span ctx or span for parent

* remove circleci config since we've moved to github actions
2020-09-22 15:48:43 -06:00
Tristan Sloughter babd248d60
update protos to v0.5.0 2020-09-05 10:54:35 -06:00
Bryan Naegele 4658ee9845
Merge pull request #13 from opentelemetry-beam/child-span-count
Remove child span count - deprecated
2020-08-27 21:40:01 -06:00
bryannaegele b521126a0d Remove child span count - deprecated 2020-08-27 21:36:14 -06:00
Bryan Naegele c9af70b7f6
Merge pull request #11 from opentelemetry-beam/atoms-support
Add support for atoms in attributes
2020-08-27 20:53:27 -06:00
bryannaegele 97dacab17d Add support for atoms in attributes 2020-08-27 20:48:57 -06:00
Bryan Naegele 2e34f1fae7
Merge pull request #10 from opentelemetry-beam/resource-env-vars
Improve the surface area of tests
2020-08-26 11:26:12 -06:00
bryannaegele f3af51ac5e add surface area to proto test 2020-08-20 12:01:51 -06:00
bryannaegele 3ddb4720d0 Add env var usage to test 2020-08-20 11:57:10 -06:00
Tristan Sloughter c2e4950656
Merge pull request #8 from opentelemetry-beam/update-otel-protos-handling
Update protos and attribute mapping
2020-07-24 15:49:16 -06:00
Bryan Naegele 9acf895177 Reset lock file 2020-07-24 14:04:27 -06:00
Bryan Naegele 61920118e0 remove span count in another commit 2020-07-22 20:26:38 -06:00
Bryan Naegele 582d6b7074
Merge branch 'master' into update-otel-protos-handling 2020-07-22 18:40:01 -06:00
Bryan Naegele 2e94b71c5e Update protos and attribute mapping 2020-07-22 18:33:41 -06:00
Tristan Sloughter 6125975033
upgrade lock of api 2020-07-21 17:55:07 -06:00
Tristan Sloughter 5048a78168
Merge pull request #7 from opentelemetry-beam/bryannaegele-patch-1
Format message body as string for non-200's
2020-07-21 08:36:21 -06:00
Bryan Naegele 245f52a919
Format message body as string for non-200's
In Elixir `~p` will just print a list of numbers in the log.
2020-07-20 18:57:39 -06:00
Tristan Sloughter 74f6c8c6ea
Merge pull request #6 from opentelemetry-beam/latest-otel-protos
update to latest otel protos
2020-07-03 11:20:56 -06:00
Tristan Sloughter 68a09097e7
use docker-compose in github actions 2020-07-02 08:33:51 -06:00
Tristan Sloughter aa09f6bc40
update to latest otel protos 2020-07-02 08:12:33 -06:00
Tristan Sloughter 2e01b4c455
Merge pull request #5 from gugahoa/patch-1
Add missing `]` from config in README.md
2020-06-30 13:05:28 -06:00
Gustavo Aguiar 2ca40e952c
Add missing `]` from config in README.md 2020-06-30 15:25:23 -03:00
Tristan Sloughter 9c84447e8c
Merge pull request #4 from opentelemetry-beam/http-1.1
http1.1 support
2020-06-06 13:01:44 -06:00
Tristan Sloughter 8c5eaf52f2
fix timestamp names, using _unix_nano not _unixnano 2020-06-06 12:53:21 -06:00
Tristan Sloughter 25955b4745
use v2 of actions/checkout and setup-erlang instead of container 2020-06-06 11:56:52 -06:00
Tristan Sloughter 1a71faf9a1
update trace service protos 2020-06-06 11:49:56 -06:00
Tristan Sloughter 538ff40d7d
use absolute path for github action services volume 2020-06-06 11:49:42 -06:00
Tristan Sloughter 44ba6fca4e
support for exporting as protobuffers over http1.1 added 2020-06-06 10:25:30 -06:00
Tristan Sloughter 3bc5e12f42
add prefix to protobuf module 2020-03-30 09:56:21 -06:00
Tristan Sloughter a6d8c34983
update deps and remove dep wts 2020-03-30 09:52:05 -06:00
Tristan Sloughter d8e005a69f
update protos and dep records 2020-03-29 20:19:39 -06:00
Tristan Sloughter 5e76e5b94d
use official otel collector dev images 2020-03-29 20:18:56 -06:00
Tristan Sloughter e5cd4098c9
update receiver port in readme 2020-03-21 15:23:03 -06:00
Tristan Sloughter 99e21dd9ff
use new otelcol preconfigured to pass config file 2020-03-21 08:44:53 -06:00
Tristan Sloughter 491a18da73
github services: use port 9090 for otelcol 2020-03-21 08:32:11 -06:00
Tristan Sloughter da4abdd338
add custom entrypoint to otelcol in github services 2020-03-21 08:30:04 -06:00
Tristan Sloughter 50d9fa63fb
use dockerhub image for otelcol bc wtf github packages 2020-03-21 08:19:08 -06:00
Tristan Sloughter 2e96a0aa0f
use 'options' in github workflow services 2020-03-21 07:59:39 -06:00
Tristan Sloughter c4321aea16
fix exporter grpc channel and add github workflow test 2020-03-21 07:51:42 -06:00
Tristan Sloughter a699629e3f
add to readme and update app metadata 2020-03-19 15:41:15 -06:00
Tristan Sloughter cc3018630b
dialyzer updates 2020-03-15 16:10:57 -06:00
Tristan Sloughter 3466cb1512
update protos to add instrumentation_library field and add resource arg 2020-03-15 15:55:02 -06:00
Tristan Sloughter d0d3be0123
add otel collector to docker-compose and functional test 2020-03-07 12:40:06 -07:00
Tristan Sloughter 65e4078804
switch to using a submodule for opentelemetry-proto 2020-03-07 11:24:08 -07:00
Tristan Sloughter 040f4775ed
initial commit 2020-02-16 15:15:22 -07:00
455 changed files with 73215 additions and 3910 deletions

View File

@ -1,78 +0,0 @@
version: 2.1
orbs:
rebar3: tsloughter/rebar3@0.8.1
codecov: codecov/codecov@1.0.5
jobs:
codecov:
parameters:
executor:
description: The executor to use for this job.
type: executor
default: erlang
executor: <<parameters.executor>>
steps:
- attach_workspace:
at: ~/project/
- codecov/upload:
file: _build/test/covertool/opentelemetry.covertool.xml
run_benchmarks:
docker:
- image: circleci/elixir:1.9
steps:
- checkout
- run: |
mix local.hex --force
mix local.rebar --force
rebar3 as bench compile
ERL_LIBS=_build/bench/lib/ mix run --no-mix-exs samples/run.exs
erlang22: &erlang22
executor:
name: rebar3/erlang
tag: "22"
erlang21: &erlang21
executor:
name: rebar3/erlang
tag: "21"
workflows:
otp21:
jobs:
- rebar3/compile:
<<: *erlang21
otp22:
jobs:
- rebar3/compile:
<<: *erlang22
- rebar3/xref:
<<: *erlang22
requires:
- rebar3/compile
- rebar3/dialyzer:
<<: *erlang22
requires:
- rebar3/compile
- rebar3/ct:
<<: *erlang22
requires:
- rebar3/compile
- rebar3/cover:
<<: *erlang22
requires:
- rebar3/ct
- codecov:
<<: *erlang22
requires:
- rebar3/cover
benchmarks:
jobs:
- run_benchmarks

3
.formatter.exs Normal file
View File

@ -0,0 +1,3 @@
[
inputs: ["{mix,.formatter}.exs", "{samples,test}/**/*.{ex,exs}"]
]

20
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,20 @@
language-elixir:
- apps/**/*.ex
- apps/**/*.exs
language-erlang:
- apps/**/*.erl
- apps/**/*.hrl
- apps/**/rebar.config
scope-api:
- apps/opentelemetry_api/**
scope-sdk:
- apps/opentelemetry/**
scope-semconv:
- apps/opentelemetry_semantic_conventions/**
scope-ci:
- .github/workflows/**

6
.github/repository-settings.md vendored Normal file
View File

@ -0,0 +1,6 @@
# Repository Settings Changes
Tracks changes to this repository's settings by admins/maintainers per [community guidelines](https://github.com/open-telemetry/community/blob/main/docs/how-to-configure-new-repository.md#collaborators-and-teams).
## Changelog

188
.github/workflows/elixir.yml vendored Normal file
View File

@ -0,0 +1,188 @@
name: Elixir
on:
pull_request:
branches:
- "main"
types: [opened, reopened, synchronize, labeled]
push:
branches:
- "main"
permissions:
contents: read
jobs:
format:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: "27.2"
elixir-version: "1.18.1"
version-type: "strict"
- uses: actions/cache@v4
name: Cache
with:
path: |
apps/opentelemetry_api/deps
key: v3-${{ hashFiles('apps/opentelemetry_api/mix.lock') }}
- run: mix format --check-formatted
- run: mix deps.get
working-directory: apps/opentelemetry_api/
- run: mix format --check-formatted
working-directory: apps/opentelemetry_api/
sdk_tests:
runs-on: ${{ matrix.os }}
name: Test SDK on Elixir ${{ matrix.elixir_version }} (OTP ${{ matrix.otp_version }}) and ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2", "25.3.2.16"]
elixir_version: ["1.18.1", "1.14.5"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
exclude:
- elixir_version: "1.14.5"
- otp_version: "27.2"
env:
OTP_VERSION: ${{ matrix.otp_version }}
ELIXIR_VERSION: ${{ matrix.elixir_version }}
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
elixir-version: ${{ matrix.elixir_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- name: Compile
run: rebar3 as test compile
- name: ExUnit
run: mix test --no-start test/otel_tests.exs test/otel_metric_tests.exs
api_tests:
runs-on: ${{ matrix.os }}
name: Test API on Elixir ${{ matrix.elixir_version }} (OTP ${{ matrix.otp_version }}) and ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2", "25.3.2.16"]
elixir_version: ["1.18.1", "1.14.5"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
exclude:
- elixir_version: "1.14.5"
- otp_version: "27.2"
env:
OTP_VERSION: ${{ matrix.otp_version }}
ELIXIR_VERSION: ${{ matrix.elixir_version }}
defaults:
run:
working-directory: apps/opentelemetry_api/
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
elixir-version: ${{ matrix.elixir_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- uses: actions/cache@v4
name: Cache
with:
path: |
apps/opentelemetry_api/deps
apps/opentelemetry_api/_build
key: ${{ runner.os }}-build-${{ matrix.otp_version }}-${{ matrix.elixir_version }}-v4-${{ hashFiles(format('{0}{1}', github.workspace, '/apps/opentelemetry_api/mix.lock')) }}
restore-keys: |
${{ runner.os }}-build-${{ matrix.otp_version }}-${{ matrix.elixir_version }}-
- run: mix deps.get
name: Deps
- run: mix test --cover
name: ExUnit
- uses: codecov/codecov-action@v5
if: ${{ always() }}
with:
file: apps/opentelemetry_api/coverage.xml
env_vars: OTP_VERSION,ELIXIR_VERSION
flags: api,elixir
dialyze:
runs-on: ${{ matrix.os }}
name: Dialyze on Elixir ${{ matrix.elixir_version }} (OTP ${{ matrix.otp_version }}) and ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2"]
elixir_version: ["1.18.1"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
env:
OTP_VERSION: ${{ matrix.otp_version }}
ELIXIR_VERSION: ${{ matrix.elixir_version }}
defaults:
run:
working-directory: apps/opentelemetry_api/
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
elixir-version: ${{ matrix.elixir_version }}
version-type: "strict"
- uses: actions/cache@v4
name: Cache
with:
path: |
apps/opentelemetry_api/deps
apps/opentelemetry_api/_build
key: ${{ runner.os }}-dialyzer-${{ matrix.otp_version }}-${{ matrix.elixir_version }}-v4-${{ hashFiles('apps/opentelemetry_api/mix.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ matrix.otp_version }}-${{ matrix.elixir_version }}-
- run: mix deps.get
name: Deps
- run: mix dialyzer
name: Dialyzer
semconv_tests:
runs-on: ${{ matrix.os }}
if: (contains(github.event.pull_request.labels.*.name, 'language-elixir') && contains(github.event.pull_request.labels.*.name, 'scope-semconv'))
name: Test SemConv on Elixir ${{ matrix.elixir_version }} (OTP ${{ matrix.otp_version }}) and ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2", "25.3.2.16"]
elixir_version: ["1.18.1", "1.14.5"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
exclude:
- elixir_version: "1.14.5"
- otp_version: "27.2"
defaults:
run:
working-directory: apps/opentelemetry_semantic_conventions
env:
OTP_VERSION: ${{ matrix.otp_version }}
ELIXIR_VERSION: ${{ matrix.elixir_version }}
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
elixir-version: ${{ matrix.elixir_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- name: Cache
uses: actions/cache@v4
with:
path: |
~/deps
~/_build
key: ${{ runner.os }}-test-${{ matrix.otp_version }}-${{ matrix.elixir_version }}-${{ hashFiles('**/mix.lock') }}
- name: Get and compile deps
if: steps.deps-cache.outputs.cache-hit != 'true'
run: |
mix deps.get
mix deps.compile
- name: ExUnit
run: mix test

173
.github/workflows/erlang.yml vendored Normal file
View File

@ -0,0 +1,173 @@
---
name: Erlang
on:
pull_request:
branches:
- "main"
types: [opened, reopened, synchronize, labeled]
push:
branches:
- "main"
permissions:
contents: read
jobs:
build:
permissions:
checks: write
name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2", "26.2.5.6", "25.3.2.16"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
env:
OTP_VERSION: ${{ matrix.otp_version }}
steps:
- uses: actions/checkout@v5
- name: Run Collector
run: docker compose up -d
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- uses: actions/cache@v4
name: Cache
with:
path: |
_build
key: ${{ runner.os }}-build-${{ matrix.otp_version }}-${{ hashFiles(format('rebar.lock')) }}-5
restore-keys: |
${{ runner.os }}-build-${{ matrix.otp_version }}-5-
- name: Compile
run: rebar3 compile
- name: EUnit tests
run: rebar3 eunit --cover
- name: Common Test tests
run: rebar3 ct --cover
- name: Publish Test Report
uses: mikepenz/action-junit-report@v5
if: success() || failure() # always run even if the previous step fails
with:
report_paths: "**/_build/test/logs/*/junit_report.xml"
- name: XRef
run: rebar3 xref
- name: Covertool
if: ${{ always() }}
run: rebar3 covertool generate
- uses: codecov/codecov-action@v5
if: ${{ always() }}
with:
file: _build/test/covertool/opentelemetry.covertool.xml
env_vars: OTP_VERSION
flags: sdk,erlang
- uses: codecov/codecov-action@v5
if: ${{ always() }}
with:
file: _build/test/covertool/opentelemetry_api.covertool.xml
env_vars: OTP_VERSION
flags: api,erlang
- uses: codecov/codecov-action@v5
if: ${{ always() }}
with:
file: _build/test/covertool/opentelemetry_exporter.covertool.xml
env_vars: OTP_VERSION
flags: exporter,erlang
- uses: codecov/codecov-action@v5
if: ${{ always() }}
with:
file: _build/test/covertool/opentelemetry_zipkin.covertool.xml
env_vars: OTP_VERSION
flags: zipkin,erlang
dialyzer:
name: Dialyze on OTP ${{ matrix.otp_version }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- uses: actions/cache@v4
name: Cache
with:
path: |
_build
key: ${{ runner.os }}-build-${{ matrix.otp_version }}-${{ hashFiles('rebar.lock') }}-5
restore-keys: |
${{ runner.os }}-dialyzer-${{ matrix.otp_version }}-5-
- name: Compile
run: rebar3 compile
- name: Dialyzer
run: rebar3 as dialyzer dialyzer
eqWAlizer:
name: EqWAlizer on OTP ${{ matrix.otp_version }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- uses: actions/cache@v4
name: Cache
with:
path: |
_build
key: ${{ runner.os }}-build-${{ matrix.otp_version }}-${{ hashFiles('rebar.lock') }}-5
restore-keys: |
${{ runner.os }}-eqWAlizer-${{ matrix.otp_version }}-5-
- name: Download elp
run: |
wget https://github.com/WhatsApp/erlang-language-platform/releases/download/2024-12-09/elp-linux-x86_64-unknown-linux-gnu-otp-27.1.tar.gz
tar xvf elp-linux-x86_64-unknown-linux-gnu-otp-27.1.tar.gz
- name: Compile
run: rebar3 compile
- name: eqWAlizer
run: ./elp eqwalize-all
semconv_tests:
runs-on: ${{ matrix.os }}
if: (contains(github.event.pull_request.labels.*.name, 'language-erlang') && contains(github.event.pull_request.labels.*.name, 'scope-semconv'))
name: Test SemConv on (OTP ${{ matrix.otp_version }}) and ${{ matrix.os }}
strategy:
matrix:
otp_version: ["27.2", "25.3.2.16"]
rebar3_version: ["3.24.0"]
os: [ubuntu-24.04]
defaults:
run:
working-directory: apps/opentelemetry_semantic_conventions
env:
OTP_VERSION: ${{ matrix.otp_version }}
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
rebar3-version: ${{ matrix.rebar3_version }}
version-type: "strict"
- name: Compile
run: rebar3 compile
- name: Common Test tests
run: rebar3 ct --cover

27
.github/workflows/fossa.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: FOSSA scanning
on:
push:
branches:
- main
permissions:
contents: read
jobs:
fossa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: erlef/setup-beam@v1
with:
otp-version: "27.2"
rebar3-version: "3.24.0"
elixir-version: "1.18.1"
version-type: "strict"
- uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
with:
api-key: ${{secrets.FOSSA_API_KEY}}
team: OpenTelemetry

15
.github/workflows/labeler.yml vendored Normal file
View File

@ -0,0 +1,15 @@
name: "Pull Request Labeler"
on: [pull_request_target]
permissions:
contents: read
jobs:
triage:
permissions:
pull-requests: write # required for labeling PRs
runs-on: ubuntu-24.04
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

View File

@ -1,39 +0,0 @@
name: Common Test
on:
pull_request:
branches:
- 'master'
push:
branches:
- 'master'
jobs:
build:
name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
otp_version: ['23.0.2', '22.3.4.2', '21.3.8.16']
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: gleam-lang/setup-erlang@v1.0.0
with:
otp-version: ${{ matrix.otp_version }}
- name: Compile
run: rebar3 compile
- name: EUnit tests
run: rebar3 eunit
- name: Dialyzer
run: rebar3 dialyzer
- name: XRef
run: rebar3 xref
- name: Covertool
run: rebar3 covertool generate
- uses: codecov/codecov-action@v1
with:
file: _build/test/covertool/opentelemetry.covertool.xml

47
.github/workflows/ossf-scorecard.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: OSSF Scorecard
on:
push:
branches:
- main
schedule:
- cron: "33 11 * * 1" # once a week
workflow_dispatch:
permissions: read-all
jobs:
analysis:
runs-on: ubuntu-latest
permissions:
# Needed for Code scanning upload
security-events: write
# Needed for GitHub OIDC token if publish_results is true
id-token: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable
# uploads of run results in SARIF format to the repository Actions tab.
# https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts
- name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11
with:
sarif_file: results.sarif

54
.github/workflows/w3c_interop.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: W3C Interop
on:
pull_request:
branches:
- 'main'
push:
branches:
- 'main'
permissions:
contents: read
jobs:
interop_tests:
name: Run W3C Trace Context Interop Tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: erlef/setup-beam@v1
with:
otp-version: '26.1.2'
version-type: strict
rebar3-version: '3.22.1'
- uses: actions/cache@v4
name: Cache
with:
path: |
_build
key: ${{ runner.os }}-build-${{ matrix.otp_version }}-${{ hashFiles(format('rebar.lock')) }}-1
restore-keys: |
${{ runner.os }}-build-${{ matrix.otp_version }}-1-
- name: Compile
run: rebar3 as interop compile
- uses: actions/checkout@v5
with:
repository: 'w3c/trace-context'
path: 'trace-context'
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: 3.13
architecture: x64
- run: pip install aiohttp
- run: |
rebar3 as interop compile
erl -noinput -pa ./_build/interop/extras/interop/ $(rebar3 as interop path) -s w3c_trace_context_interop &
sleep 1
cd trace-context/test
STRICT_LEVEL=2 python3 test.py http://127.0.0.1:5000/test
shell: bash

3
.gitignore vendored
View File

@ -17,3 +17,6 @@ _build
*.iml
rebar3.crashdump
*~
doc
!_index.md
guides

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "apps/opentelemetry_exporter/opentelemetry-proto"]
path = apps/opentelemetry_exporter/opentelemetry-proto
url = https://github.com/open-telemetry/opentelemetry-proto.git

656
CHANGELOG.md Normal file
View File

@ -0,0 +1,656 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## API 1.4.1 - 2025-07-31
### Fixes
- Various type spec fixes
## SDK 1.5.1 - 2025-07-31
### Fixes
- [fix the batch export timeout to default to 30 seconds](https://github.com/open-telemetry/opentelemetry-erlang/pull/836)
## OTLP Exporter 1.8.1 - 2025-07-31
### Fixes
- [fix: key for otlp traces protocol app configuration](https://github.com/open-telemetry/opentelemetry-erlang/pull/789)
## Experimental API 0.5.2 - 2024-11-22
### Added
- [Hard code semconv values](https://github.com/open-telemetry/opentelemetry-erlang/pull/780)
## Experimental SDK 0.6.0 - 2024-11-22
### Added
- [move metrics and logs to separate exporter modules from
traces](https://github.com/open-telemetry/opentelemetry-erlang/pull/720)
- [make the console metric exporter handle all
values](https://github.com/open-telemetry/opentelemetry-erlang/pull/709)
### Fixes
- [metric exporter: nothing to do for an empty list of
metrics](https://github.com/open-telemetry/opentelemetry-erlang/pull/782)
- [Hard code semconv
values](https://github.com/open-telemetry/opentelemetry-erlang/pull/780)
- [removed old unused otel_metric_exporter
module](https://github.com/open-telemetry/opentelemetry-erlang/pull/715)
## Exporter 1.8.0 - 2024-10-05
### Fixes
- [BREAKING: Fixes support for attribute values that are lists when the elements
are strings. Lists of strings in attribute values are no longer flattened but
remain lists. Meaning to use an Erlang charlist string or iolist as a value in
an attribute you must convert with `unicode:characters_to_binary` before
adding to the
attributes](https://github.com/open-telemetry/opentelemetry-erlang/pull/737)
## API 1.4.0 - 2024-10-05
### Changes
- [Hard code semconv 0.2 values](https://github.com/open-telemetry/opentelemetry-erlang/pull/780)
## SDK 1.5.0 - 2024-10-05
### Changes
- [Fix invalid warning log causing FORMATTER
CRASH](https://github.com/open-telemetry/opentelemetry-erlang/pull/774)
- [Hard code semconv 0.2 values](https://github.com/open-telemetry/opentelemetry-erlang/pull/780)
## API 1.3.1 - 2024-09-03
### Fixes
- [Fix dialyzer warning when starting a span by adding
`otel_span:start_config`](https://github.com/open-telemetry/opentelemetry-erlang/pull/717)
## Experimental API 0.5.1 - 2024-03-18
### Added
- [instrument kind temporality function for use by the
SDK](https://github.com/open-telemetry/opentelemetry-erlang/pull/713)
## Experimental SDK 0.5.1 - 2024-03-18
### Fixes
- [use correct default temporality for streams based on the instrument
kind](https://github.com/open-telemetry/opentelemetry-erlang/pull/713)
## API 1.3.0 - 2024-03-15
### Changes
- [Add `otel_tracestate` module for creating and updating
tracestate](https://github.com/open-telemetry/opentelemetry-erlang/pull/607)
- [Attributes module `otel_attributes` moved to
API](https://github.com/open-telemetry/opentelemetry-erlang/pull/618)
- [Moved attribute processing functions to `otel_attributes` from
`otel_span`](https://github.com/open-telemetry/opentelemetry-erlang/pull/620)
## SDK 1.4.0 - 2024-03-15
### Changes
- [Attributes module `otel_attributes` moved to
API](https://github.com/open-telemetry/opentelemetry-erlang/pull/618)
- [create unique processor name in
otel_tracer_server](https://github.com/open-telemetry/opentelemetry-erlang/pull/646)
### Fixes
- [Fix leak of atoms/persistent terms by creating unique processor name in `otel_tracer_server`](https://github.com/open-telemetry/opentelemetry-erlang/pull/646)
- [fix(otel_batch_processor): don't divide `max_queue_size` by
word-size](https://github.com/open-telemetry/opentelemetry-erlang/pull/635)
- [fix(otel_processor): wait for runner process
termination](https://github.com/open-telemetry/opentelemetry-erlang/pull/641)
## Exporter 1.7.0 - 2024-03-15
## Added
- [Add User-Agent header to exporter
requests](https://github.com/open-telemetry/opentelemetry-erlang/pull/605)
## Experimental API 0.5.0 - 2024-03-15
### Changes
- [Allow to create observable instruments without passing callback
arguments](https://github.com/open-telemetry/opentelemetry-erlang/pull/604)
- [Allow to give `advisory_params` to instrument creation functions](https://github.com/open-telemetry/opentelemetry-erlang/pull/628)
- [Attributes are optional in Counter.add(), UpDownCounter.add() and Histo.record()](https://github.com/open-telemetry/opentelemetry-erlang/pull/632)
- [Support explicit_bucket_boundaries advisory
parameters](https://github.com/open-telemetry/opentelemetry-erlang/pull/628)
## Experimental SDK 0.5.0 - 2024-03-15
### Added
- [Add `instrument_unit` to view criteria](https://github.com/open-telemetry/opentelemetry-erlang/pull/604)
- [Validate instrument name](https://github.com/open-telemetry/opentelemetry-erlang/pull/604)
- [Handle `explicit_bucket_boundaries` advisory parameter](https://github.com/open-telemetry/opentelemetry-erlang/pull/628)
- [Rename `boundaries` to `explicit_bucket_boundaries` in histogram explicit aggregation options](https://github.com/open-telemetry/opentelemetry-erlang/pull/628)
- [Allow creating wildcard views](https://github.com/open-telemetry/opentelemetry-erlang/pull/624)
- [Exemplars support](https://github.com/open-telemetry/opentelemetry-erlang/pull/692)
- [Metric
producers](https://github.com/open-telemetry/opentelemetry-erlang/pull/701)
- [Exemplar reservoir support](https://github.com/open-telemetry/opentelemetry-erlang/pull/692)
### Changes
- [Align histogram default boundaries with specification](https://github.com/open-telemetry/opentelemetry-erlang/pull/614)
- [Metrics: fix observable callbacks to return a list of
results](https://github.com/open-telemetry/opentelemetry-erlang/pull/561)
- [Add a fresh context to each observable callback and test observe
exemplars](https://github.com/open-telemetry/opentelemetry-erlang/pull/697)
### Fixes
- [Correctly record histogram values greater than last boundary](https://github.com/open-telemetry/opentelemetry-erlang/pull/614)
- [Readers should use a default cumulative temporality if not specified](https://github.com/open-telemetry/opentelemetry-erlang/pull/613)
- [Check for positive data values in counters and histograms](https://github.com/open-telemetry/opentelemetry-erlang/pull/632)
- [Fix Delta metric export to only include those recorded in collection cycle](https://github.com/open-telemetry/opentelemetry-erlang/pull/677)
- [Cumulative sums
fix](https://github.com/open-telemetry/opentelemetry-erlang/pull/592)
- [Fix transmitted time units for
logs](https://github.com/open-telemetry/opentelemetry-erlang/pull/640)
- [don't export unit fields in metrics when the unit is
undefined](https://github.com/open-telemetry/opentelemetry-erlang/pull/669)
## SDK 1.3.1 - 2023-08-15
### Added
- [Add support for OTEL_SDK_DISABLED environment variable and sdk_disabled
application environment
variable](https://github.com/open-telemetry/opentelemetry-erlang/pull/574)
### Changes
- [Resource is now an argument to TracerProvider start, but still set
automatically by SDK startup of the global
Provider](https://github.com/open-telemetry/opentelemetry-erlang/pull/568)
- [Global Tracer no longer set to no-op on SDK
shutdown](https://github.com/open-telemetry/opentelemetry-erlang/pull/568)
- [Remove use of `deprecated` module attribute to support
OTP-22](https://github.com/open-telemetry/opentelemetry-erlang/pull/603)
### Fixes
- [Fixed parsing of key/value list configuration where value has = in
it](https://github.com/open-telemetry/opentelemetry-erlang/pull/596)
## API 1.2.2 - 2023-08-15
### Changes
- [Remove use of `deprecated` module attribute to support
OTP-22](https://github.com/open-telemetry/opentelemetry-erlang/pull/603)
## Exporter 1.6.0 - 2023-06-21
### Changes
- [Update OTLP protos to
0.20.0](https://github.com/open-telemetry/opentelemetry-erlang/pull/598)
## Exporter 1.5.0 - 2023-05-19
### Fixes
- [only start inets httpc profile if it doesn't
exist](https://github.com/open-telemetry/opentelemetry-erlang/pull/591)
## Exporter 1.4.1 - 2023-04-26
### Fixes
- [Relax version constraints on API and
SDK](https://github.com/open-telemetry/opentelemetry-erlang/pull/578)
## SDK 1.3.0 - 2023-03-21
### Fixes
- [Fix swapping exporter
tables](https://github.com/open-telemetry/opentelemetry-erlang/pull/559)
## Exporter 1.4.0 - 2023-02-21
### Fixes
- [bump tls_certificate_check to fix crash on OTP-25](https://github.com/open-telemetry/opentelemetry-erlang/pull/547)
## API v1.2.1 - 2023-02-21
### Fixes
- [Have set_status check is_recording in all cases](https://github.com/open-telemetry/opentelemetry-erlang/pull/540)
- [Using opentelemetry_semantic_conventions for record_exception](https://github.com/open-telemetry/opentelemetry-erlang/pull/537)
## Experimental SDK 0.3.0 - 2023-02-21
### Fixes
- [metrics: fix updating delta timestamps in aggregations](https://github.com/open-telemetry/opentelemetry-erlang/pull/546)
- [Move is_monotonic check to the SDK](https://github.com/open-telemetry/opentelemetry-erlang/pull/544)
## Experimental API 0.3.0 - 2023-02-21
### Fixes
- [Move is_monotonic check to the SDK](https://github.com/open-telemetry/opentelemetry-erlang/pull/544)
## Exporter 1.2.2 - 2022-10-21
### Fixes
- [Allow multiple instances of OTLP grpc
connections](https://github.com/open-telemetry/opentelemetry-erlang/pull/481)
## Experimental API 0.1.0 - 2022-10-19
### Added
- Erlang Metrics API
### Removed
- [Old experimental metrics
api](https://github.com/open-telemetry/opentelemetry-erlang/pull/479)
## Experimental SDK 0.1.0 - 2022-10-19
### Added
- Metrics SDK
- Logging handler and exporter
- [Delta support for explicit
histogram](https://github.com/open-telemetry/opentelemetry-erlang/pull/475)
- [Logging
Handler](https://github.com/open-telemetry/opentelemetry-erlang/pull/468)
- [OTLP Metrics
exporting](https://github.com/open-telemetry/opentelemetry-erlang/pull/456)
### Fixed
- [Fix OTLP Protocol allowed
values](https://github.com/open-telemetry/opentelemetry-erlang/pull/420)
## API 1.1.1 - 2022-10-19
### Fixed
- Gradualizer cleanup of type specs
## SDK 1.1.2 - 2022-10-19
#### Added
- [Replaced telemetry_library record with library info as resource
attributes](https://github.com/open-telemetry/opentelemetry-erlang/pull/457)
## Exporter 1.2.1 - 2022-09-08
### Fixes
- Gradualizer cleanup
## Exporter 1.2.0 - 2022-09-08
### Fixes
- [Fix InstrumentationScope encoding in OTLP
protobufs](https://github.com/open-telemetry/opentelemetry-erlang/pull/451)
### Added
- [Exporter now respects top-level `ssl_options` application environment value
and handles endpoint parse errors](https://github.com/open-telemetry/opentelemetry-erlang/pull/442)
## SDK 1.1.1 - 2022-09-02
### Added
- [Flush Trace Provider on application
shutdown](https://github.com/open-telemetry/opentelemetry-erlang/pull/470)
### Fixes
- Fix dependency on API to require `~> 1.1`
## Exporter 1.1.1 - 2022-09-02
### Fixes
- Fix dependency on API and SDK to require `~> 1.1`
## Zipkin Exporter 1.1.0 - 2022-09-02
### Fixes
- Support `opentelemetry_sdk ~> 1.1` exporter API
## API 1.1.0 - 2022-8-31
#### Added
- [Span context now set in logger metadata when context is updated in process
dictionary](https://github.com/open-telemetry/opentelemetry-erlang/pull/394)
- [Instrumentation Scope replaces Instrumentation
Library](https://github.com/open-telemetry/opentelemetry-erlang/pull/405) --
If you were using the record directly, please use the function
`opentelemetry:instrumentation_scope/3` or
`opentelemetry:instrumentation_library/3` to create an `instrumentation_scope`
record.
## SDK 1.1.0 - 2022-8-31
#### Added
- [Instrumentation Scope replaces Instrumentation
Library](https://github.com/open-telemetry/opentelemetry-erlang/pull/405) --
If you were using the record directly, please use the function
`opentelemetry:instrumentation_scope/3` or
`opentelemetry:instrumentation_library/3` to create an `instrumentation_scope`
record.
### Fixed
- [Allow custom text propagator to be configured via application
env](https://github.com/open-telemetry/opentelemetry-erlang/pull/408)
- [No longer grow export table in batch processor if no export table is
configured](https://github.com/open-telemetry/opentelemetry-erlang/pull/413)
## Exporter 1.1.0 - 2022-8-31
#### Added
- [Instrumentation Scope replaces Instrumentation
Library](https://github.com/open-telemetry/opentelemetry-erlang/pull/405) --
If you were using the record directly, please use the function
`opentelemetry:instrumentation_scope/3` or
`opentelemetry:instrumentation_library/3` to create an `instrumentation_scope`
record.
## Experimental API/SDK
#### Added
- [Initial work to support the stable spec for the Metrics API and
SDK](https://github.com/open-telemetry/opentelemetry-erlang/pull/412)
## SDK 1.0.5 - 2022-05-20
### Fixed
- [span processor config: don't override user settings with
defaults](https://github.com/open-telemetry/opentelemetry-erlang/pull/397)
## SDK 1.0.4 - 2022-05-13
### Fixed
- [Setting the exporter with `traces_exporter` application environment variable
now properly overrides the configuration passed to the
processor](https://github.com/open-telemetry/opentelemetry-erlang/pull/393)
## Exporter 1.0.4 - 2022-05-06
- [fix bug where port 80 is used even for https](https://github.com/open-telemetry/opentelemetry-erlang/pull/389)
## 1.0.3 - 2022-04-27
### [API 1.0.3]
- Doc fixes and improvements to `tracer.ex` and `otel_propagator_text_map.erl`
### [SDK 1.0.3]
- [Improve performance of Span set_status](https://github.com/open-telemetry/opentelemetry-erlang/pull/384)
### [Exporter 1.0.3]
- [Fix use of `otlp_endpoint` configuration from Elixir](https://github.com/open-telemetry/opentelemetry-erlang/pull/376)
- [Remove the SDK application `opentelemetry` from the Exporter's runtime dependencies](https://github.com/open-telemetry/opentelemetry-erlang/pull/387)
## 1.0.2 - 2022-02-22
### [API 1.0.2]
#### Added
- [Docs for Erlang and Elixir macros added](https://github.com/open-telemetry/opentelemetry-erlang/pull/362)
### [SDK 1.0.2]
#### Added
- [Simpler configuration of span processors](https://github.com/open-telemetry/opentelemetry-erlang/pull/357)
#### Fixed
- Span Status: Ignore status changes that don't follow the [define precedence in
the spec](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-status)
### [Zipkin Exporter 1.0.0]
#### Fixed
- [Attribute values that are lists are converted to strings in Zipkin tags](https://github.com/open-telemetry/opentelemetry-erlang/pull/363)
- [Status converted to Zipkin tags](https://github.com/open-telemetry/opentelemetry-erlang/pull/363)
## 1.0.1 - 2022-02-03
### [API]
#### Fixed
- [W3C Tracestate: Keep last value for duplicate key](https://github.com/open-telemetry/opentelemetry-erlang/pull/346)
- [add report_cb to format log messages in composite propagator to have more
detailed logs](https://github.com/open-telemetry/opentelemetry-erlang/pull/355)
- [Fix use of wrong timestamp format on events](https://github.com/open-telemetry/opentelemetry-erlang/pull/354)
#### Fixed
### [SDK]
- [Fix use of wrong timestamp format on events](https://github.com/open-telemetry/opentelemetry-erlang/pull/354)
### [Exporter]
#### Fixed
- [use the default port of the scheme (http/https) instead of default OTLP
port](https://github.com/open-telemetry/opentelemetry-erlang/pull/354)
## 1.0.0 - 2022-01-03
### [SDK]
#### Fixed
- [SDK will continue to try initializing exporter if it fails to resolve startup
ordering issues](https://github.com/open-telemetry/opentelemetry-erlang/pull/338)
- [elixir span docs: fix reference to attributes
type](https://github.com/open-telemetry/opentelemetry-erlang/pull/336)
### [API]
#### Fixed
- [events: accept map for attributes on an event](https://github.com/open-telemetry/opentelemetry-erlang/pull/335)
### [Exporter]
#### Added
- New `opentelemetry_exporter` application environment options:
- `otlp_protocol`: The transport protocol, supported values: `grpc` and `http_protobuf`. Defaults to `http_protobuf`.
- `otlp_traces_protocol`: The transport protocol to use for exporting traces, supported values: `grpc` and `http_protobuf`. Defaults to `http_protobuf`.
- `otlp_compression`: Compression type to use, supported values: `gzip`. Defaults to no compression.
- `otlp_traces_compression`: Compression type to use for exporting traces, supported values: `gzip`. Defaults to no compression.
- New environment variable options:
- `OTEL_EXPORTER_OTLP_PROTOCOL`: The transport protocol to use, supported values: `grpc` and `http_protobuf`. Defaults to `http_protobuf`
- `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`: The transport protocol to use for exporting traces, supported values: `grpc` and `http_protobuf`. Defaults to `http_protobuf`.
- `OTEL_EXPORTER_OTLP_COMPRESSION`: Compression to use, supported value: gzip. Defaults to no compression.
- `OTEL_EXPORTER_OTLP_TRACES_COMPRESSION`: Compression to use when exporting traces, supported value: gzip. Defaults to no compression.
## [API 1.0.0-rc.4.1] - 2021-12-28
##### Fixed
- `add_event` function and macros fixed to accept both a map of attributes or a
list.
## [API 1.0.0-rc.4] - 2021-12-25
### Added
- Looking up a Tracer for a module is now done by first looking up the
OTP Application name and then the Tracer using that name. This means all
Tracers share the same "namespace" again which saves space by not duplicating
the Tracer record for every module.
- Configurable limits for the number of Attributes, Events and Links allowed in
a Span, an Event or a Link -- defaults to 128. The length of each Attribute's
value can also be limited but has a default of infinity.
Environment variables added to configure the limits:
- `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`: Limit on number of Attributes on a Span.
- `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT`: Limit length of Attribute values.
- `OTEL_SPAN_EVENT_COUNT_LIMIT`: Limit number of Events on a Span.
- `OTEL_SPAN_LINK_COUNT_LIMIT`: Limit number of Links on a Span.
- `OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT`: Limit on number of Attributes on an Event.
- `OTEL_LINK_ATTRIBUTE_COUNT_LIMIT`: Limit on number of Attributes on a Link.
- Support for a Schema URL in a Resource and in the Instrumentation Library
information of a Tracer. For more information about Schema URLs see the
specification for [Resources](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/resource/sdk.md)
and [getting a Tracer](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md).
- `OTEL_CREATE_APPLICATION_TRACERS` is a new environment variable,
`create_application_tracers` is the application environment key, for disabling
the automatic creation of Tracers for every Application at boot. The old keys,
`OTEL_REGISTER_LOADED_APPLICATIONS` and `register_loaded_applications`, will
continue to work as well.
### Fixed
- Attribute values now validate against what is allowable per the specification
rather than allowing anything the protobuf could encode. This may be breaking
to some users who were relying on the incorrect behavior, such as allowing
dictionaries or non-homogeneous lists/tuples. The one exception we have
kept is continuing to allow atoms in place of binaries for performance.
- Attribute values of type list/tuple must be homogeneous.
- Span start opts are now validated. Previously, opts underwent no validations.
- Event and link attributes are now validated. Previously only span attributes
were validated.
- Events accept atoms for the name again.
### Removed
- The `sampler` option to `start_span` and `with_span` was removed.
- `register_tracer` has been removed and now `get_tracer` will cache the Tracer
after creation if needed.
## [API 1.0.0-rc.3.2] - 2021-10-13
##### Fixed
- `otel_propagator_trace_context:extract/1` no longer crashes on `undefined`
header values
## [API 1.0.0-rc.3.1] - 2021-10-12
##### Fixed
- Properly published the package with Erlang and Elixir source. Package for
1.0.0-rc.3 was retired on Hex.pm
## [API 1.0.0-rc.3] - 2021-10-12
### Removed
- Removed `opentelemetry:register_application_tracer`. Each application has a
Tracer registered for it automatically on boot. This can be disabled by
setting `opentelemetry` environment variable `register_loaded_applications` to
`false`.
- Named Tracers registered with `opentelemetry:register_tracer` are now stored
separately from the mapping of Named Tracers created for each
application. Meaning if you have a module `mod_a` in application `app_a` with
application vsn `0.1.0` and also manually register a Tracer named `mod_a` with
version `1.1.1` then use of macros like `?with_span` will use the `app_a`
version `0.1.0` Named Tracer and manual use of a Named Tracer like:
```
Tracer = opentelemetry:get_tracer(mod_a),
otel_tracer:with_span(Tracer, span_name, #{}, fun() -> ... end),
```
will use Named Tracer `mod_a` with version `1.1.1`. In previous versions after
registering a Tracer named `mod_a` it would override the `mod_a` pointing to
the `app_a` Tracer.
Additionally, manual registration of a Named Tracer with the name `app_a` will
not override the application registered Tracer of `app_a`.
#### Context
##### Added
- B3 single header format support added
##### Changed
- Propagators must now be implementations of a propagator type's behaviour. At
this time only the `otel_propagator_text_map` behaviour exists. Callbacks for
inject and extract take an optional "set" and "get" function for working with
a carrier.
- Configuration of propagators is now a list of atoms representing either the
name of a builtin propagator (at this time those are, `trace_context`, `b3`,
`b3multi` and `baggage`) or the name of a module implementing the
propagator's behaviour.
- Default configuration: `{text_map_propagators, [trace_context, baggage]}`
- Injectors and extractors can be configured separately instead of using the
same list of propagators for both by configuring `text_map_injectors` and
`text_map_extractors`.
- For example you may want your service to support receiving `b3multi` headers
but have no need for it including `b3multi` headers when it is propagating to
other services:
```
{text_map_injectors, [trace_context, baggage]},
{text_map_extractors, [b3multi, trace_context, baggage]}
```
##### Fixed
- `b3` propagator renamed `b3multi` to properly convey it is the version of the
B3 spec that creates multiple headers
## [SDK - 1.0.0-rc.3] - 2021-10-12
### Fixed
- Memory leak fix: Non-recording Spans are no longer inserted into the ETS table tracking active span.
- Ratio based root span sampling fixed, before it didn't take into account the
generated trace id.

View File

@ -5,7 +5,7 @@
#####################################################
#
# Learn about membership in OpenTelemetry community:
# https://github.com/open-telemetry/community/blob/master/community-membership.md
# https://github.com/open-telemetry/community/blob/main/community-membership.md
#
#
# Learn about CODEOWNERS file format:

114
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,114 @@
# Development Setup Guide for Erlang Repository
## Introduction
Welcome to the Erlang Repository! 🎉
This guide aims to assist contributors in setting up their local development environment. Feel free to suggest improvements or raise questions in your contributions.
## Pre-requisites
To work with this repository, you'll need the following tools and dependencies:
- **Erlang/OTP Version** :
- We support the latest major release plus the prior two releases, aligning with Ericssons version support policy for Erlang itself.
- For a definitive list of supported versions, refer to the [erlang.yml](.github/workflows/erlang.yml) file in this repository.
If using the Elixir API:
* Elixir 1.14+
* For a definitive list of supported versions, refer to the [elixir.yml](.github/workflows/elixir.yml) file in this repository.
* Refer to the official [Erlang Installation Guide](https://www.erlang.org/downloads) for setting up Erlang.
## Local Run/Build
### Setting Up and Running the Project Locally
To run the project locally, follow these steps:
Start required services:
```
docker compose up -d
```
Set up Erlang/OTP and Rebar3 and Verify setup (Ensure you have the correct versions as specified in the prerequisites):
Run the compilation step to check for errors:
```
rebar3 compile
```
## Testing
To execute tests, use the following commands:
### Unit Tests (EUnit):
```
rebar3 eunit
```
### Integration and Functional Tests (Common Test):
```
rebar3 ct
```
### Test results and logs can be viewed in a browser by opening:
```
build/test/logs/index.html
```
### Elixir Tests
Elixir tests are run in two places:
1. Inside apps/opentelemetry_api/:
```
mix test
```
2. At the top level:
```
mix test --no-start test/otel_tests.exs test/otel_metric_tests.exs
```
## Contribution Rules
Please review the [OpenTelemetry Specification](https://opentelemetry.io/docs/specs/otel/) for details on coding standards, commit message formatting, and the contribution process.
## Troubleshooting Guide
### Debugging Common Failures
* Test Failures: Check the test logs in _build/test/logs/.
* Compilation Issues: Ensure correct OTP and Rebar3 versions are installed.
* Dialyzer Warnings: Ensure rebar3 compile completes successfully.
## Developer Setup and Language Servers
For improved development experience, consider using the following Language Server Protocols (LSPs):
* Erlang LSP: [Erlang Language Platform](https://whatsapp.github.io/erlang-language-platform/)
* Installing it removes the need for an additional type-checking step:
```
elp eqwalize-all
```
* Install from: [Erlang Language Platform Releases](https://github.com/WhatsApp/erlang-language-platform/releases/)
* Elixir LSP: [Elixir LS](https://github.com/elixir-lsp/elixir-ls)
## Further Help
* If you encounter any issues or have questions, feel free to open an issue or reach out to the maintainers.
* Join our [slack](https://cloud-native.slack.com/archives/C01N75YMZCN) channel also for further help and discussions

220
README.md
View File

@ -1,44 +1,118 @@
OpenTelemetry
=====
## OpenTelemetry Erlang/Elixir
[![EEF Observability WG project](https://img.shields.io/badge/EEF-Observability-black)](https://github.com/erlef/eef-observability-wg)
[![Hex.pm](https://img.shields.io/hexpm/v/opentelemetry)](https://hex.pm/packages/opentelemetry)
![Build Status](https://github.com/open-telemetry/opentelemetry-erlang/workflows/Common%20Test/badge.svg)
---
OpenTelemetry stats collection and distributed tracing framework for Erlang.
<p align="center">
<a href="https://hex.pm/packages/opentelemetry_api">
<img
src="https://img.shields.io/hexpm/v/opentelemetry_api?label=API&amp;style=for-the-badge"
alt="Hex.pm" />
</a>
<a href="https://hex.pm/packages/opentelemetry">
<img
src="https://img.shields.io/hexpm/v/opentelemetry?label=SDK&amp;style=for-the-badge"
alt="Hex.pm" />
</a>
<a href="https://hex.pm/packages/opentelemetry_exporter">
<img
src="https://img.shields.io/hexpm/v/opentelemetry_exporter?label=OTLP%20Exporter&amp;style=for-the-badge"
alt="Hex.pm" />
</a>
<a href="https://github.com/erlef/eef-observability-wg">
<img
src="https://img.shields.io/badge/EEF-Observability-black?style=for-the-badge"
alt="EEF Observability WG project" />
</a>
</p>
Requires OTP 21.3 or above.
<p align="center">
<a href="https://github.com/open-telemetry/opentelemetry-erlang/actions">
<img src="https://img.shields.io/github/actions/workflow/status/open-telemetry/opentelemetry-erlang/erlang.yml?style=for-the-badge&branch=main" alt="GitHub Workflow Status" />
</a>
<img src="https://img.shields.io/codecov/c/github/open-telemetry/opentelemetry-erlang?style=for-the-badge" alt="Codecov" />
</p>
---
[OpenTelemetry](https://opentelemetry.io/) distributed tracing framework for
Erlang and Elixir.
These applications implement version 1.8.0 of the [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification),
see the [spec compliance
matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md)
for a list of features supported.
## Requirements
- Erlang/OTP 23+ (With best effort for OTP 22 support)
If using the Elixir API:
- Elixir 1.13+
## Contacting Us
We hold weekly meetings. See details at [community page](https://github.com/open-telemetry/community#special-interest-groups).
We use [GitHub
Discussions](https://github.com/open-telemetry/opentelemetry-erlang/discussions)
for support or general questions. Feel free to drop us a line.
We are also present in the #otel-erlang-elixir channel in the [CNCF
slack](https://slack.cncf.io/). Please join us for more informal discussions.
You can also find us in the #opentelemetry channel on [Elixir
Slack](https://elixir-slackin.herokuapp.com/).
## Getting Started
You can find a getting started guide on [opentelemetry.io](https://opentelemetry.io/docs/instrumentation/erlang/getting-started/).
To start capturing distributed traces from your application it first needs to be
instrumented. The easiest way to do this is by using an instrumentation library.
There are a number of [officially supported instrumentation
libraries](https://github.com/open-telemetry/opentelemetry-erlang-contrib) for
popular Erlang and Elixir libraries and frameworks.
## Design
The [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification) defines a language library as having 2 components, the API and the SDK. The API must not only define the interfaces of any implementation in that language but also be able to function as a noop implementation of the tracer. The SDK is the default implementation of the API that must be optional.
The [OpenTelemetry
specification](https://github.com/open-telemetry/opentelemetry-specification)
defines a language library as having two components, the API and the SDK. The API
must not only define the interfaces of any implementation in that language but
also be able to function as a noop implementation of the tracer. The SDK is the
default implementation of the API that must be optional.
If you are instrumenting a project your application should only depend on the [OpenTelemetry API](https://github.com/open-telemetry/opentelemetry-erlang-api/) application.
When instrumenting a project, your application should only depend on the
[OpenTelemetry API](https://hex.pm/packages/opentelemetry_api) application,
found in directory `apps/opentelemetry_api` of this repo. The API is published as
the Hex package [opentelemetry_api](https://hex.pm/packages/opentelemetry_api).
This repository is the Erlang's SDK implementation and should be included in the final release and configured to setup the sampler, span processors and span exporters.
The SDK implementation, found under `apps/opentelemetry` and Hex package
[opentelemetry](https://hex.pm/packages/opentelemetry), should be included in an
OTP Release along with an exporter.
## Using
Example of Release configuration in `rebar.config`:
In an Erlang project add `opentelemetry` as the first element of the release's applications:
```erlang
{relx, [{release, {my_instrumented_release, "0.1.0"},
[opentelemetry_exporter,
{opentelemetry, temporary},
my_instrumented_app]},
``` erlang
{relx, [{release, {<name>, <version>},
[{opentelemetry, temporary},
<your applications>]},
...]}.
...]}.
```
In the above example `opentelemetry` is set to `temporary` so that if the `opentelemetry` application crashes, or is shutdown, it does not terminate the other applications in the project. This is optional, the `opentelemetry` application purposely sticks to `permanent` for the processes started by the root supervisor to leave it up to the end user whether they want the crash or shutdown or `opentelemetry` to be ignored or cause the shutdown of the rest of the applications in the release.
Example configuration for [mix's Release
task](https://hexdocs.pm/mix/Mix.Tasks.Release.html):
Doing the same for an Elixir project would be:
``` elixir
```elixir
def project do
[
...
releases: [
<name>: [
applications: [opentelemetry: :temporary]
my_instrumented_release: [
applications: [opentelemetry_exporter: :permanent, opentelemetry: :temporary]
],
...
@ -47,45 +121,109 @@ def project do
end
```
## Benchmarks
Note that you also need to add `opentelemetry_exporter` before your other `opentelemetry` dependencies in `mix.exs`,
so that it starts before `opentelemetry` does.
Running benchmarks is done with [benchee](https://github.com/bencheeorg/benchee). Benchmark functions are in modules under `samples/`. To run them open a rebar3 shell in the `bench` profile:
In the above example `opentelemetry_exporter` is listed first, ensuring that all of its
dependencies are booted before `opentelemetry` attempts to start the
exporter. `opentelemetry` is set to `temporary` so that if the `opentelemetry`
application crashes, or is shutdown, it does not terminate the other
applications in the project -- `opentelemetry_exporter` does not need to be
`temporary` because it does not have a startup and supervision tree. This is
optional; the `opentelemetry` application purposely sticks to `permanent` for
the processes started by the root supervisor to leave it up to the end user
whether they want the crash or shutdown or `opentelemetry` to be ignored or
cause the shutdown of the rest of the applications in the release.
``` shell
$ rebar3 as bench compile
## Git Dependencies
> ot_benchmarks:run().
While it is recommended to use the Hex packages for the
[API](https://hex.pm/packages/opentelemetry_api),
[SDK](https://hex.pm/packages/opentelemetry) and [OTLP
exporter](https://hex.pm/packages/opentelemetry_exporter), there are times
depending on the git repo is necessary. Because the OpenTelemetry OTP
Applications are kept in a single repository, under the directory `apps`, either
[rebar3's](https://rebar3.org) `git_subdir` (rebar 3.14 or above is required) or
[mix's](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html)
`sparse` feature must be used when using these as Git dependencies in a project. The
blocks below show how the git repo for the API and/or SDK
Applications can be used in rebar3 and mix.
```erlang
{opentelemetry_api, {git_subdir, "http://github.com/open-telemetry/opentelemetry-erlang", {branch, "main"}, "apps/opentelemetry_api"}},
{opentelemetry, {git_subdir, "http://github.com/open-telemetry/opentelemetry-erlang", {branch, "main"}, "apps/opentelemetry"}},
{opentelemetry_exporter, {git_subdir, "http://github.com/open-telemetry/opentelemetry-erlang", {branch, "main"}, "apps/opentelemetry_exporter"}}
```
If an Elixir script is wanted for the benchmarks they could be run like:
```elixir
{:opentelemetry_api, github: "open-telemetry/opentelemetry-erlang", sparse:
"apps/opentelemetry_api", override: true},
{:opentelemetry, github: "open-telemetry/opentelemetry-erlang", sparse:
"apps/opentelemetry", override: true},
{:opentelemetry_exporter, github: "open-telemetry/opentelemetry-erlang", sparse: "apps/opentelemetry_exporter", override: true}
```
``` shell
$ ERL_LIBS=_build/bench/lib/ mix run --no-mix-exs samples/run.exs
The `override: true` is required because the SDK Application, `opentelemetry`, has
the API in its `deps` list of its `rebar.config` as a Hex dependency and this will
clash when `mix` tries to resolve the dependencies and fail without the
override. `override: true` is also used on the SDK because the
`opentelemetry_exporter` application depends on it and the API as Hex deps so if
it is included the override is necessary.
## Benchmarks
Running benchmarks is done with [benchee](https://github.com/bencheeorg/benchee). Benchmark functions are stored in modules, under `samples/`. To run them, open a rebar3 shell in the `bench` profile:
```shell
$ rebar3 as bench shell
> otel_benchmarks:run().
```
If an Elixir script is wanted for the benchmarks they could be run (after
running `rebar3 as bench compile`) as follows:
```shell
$ ERL_AFLAGS="-pa ./_build/bench/extras/samples/" ERL_LIBS=_build/bench/lib/ mix run --no-mix-exs samples/run.exs
```
## W3C Trace Context Interop Tests
Start the interop web server in a shell:
``` shell
```shell
$ rebar3 as interop shell
> w3c_trace_context_interop:run().
> w3c_trace_context_interop:start().
```
Then, clone the [W3C Trace Context repo](https://github.com/w3c/trace-context) and run the tests:
``` shell
```shell
$ cd test
$ python3 test.py http://127.0.0.1:5000/test
```
## Contributing
Approvers:
- [Fred Hebert](https://github.com/ferd), Postmates Inc.
### Maintainers
Maintainers:
- [Łukasz Jan Niemier](https://github.com/hauleth),
- [Ilya Khaprov](https://github.com/deadtrickster), KOBIL Systems
- [Tristan Sloughter](https://github.com/tsloughter), Postmates Inc.
- [Bryan Naegele](https://github.com/bryannaegele), [Simplebet](https://simplebet.io/)
- [Iliia Khaprov](https://github.com/deadtrickster), [VMWare](https://www.vmware.com/)
- [Łukasz Jan Niemier](https://github.com/hauleth)
- [Tristan Sloughter](https://github.com/tsloughter), [Splunk](https://www.splunk.com/en_us/observability/apm-application-performance-monitoring.html)
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
### Approvers
- [Fred Hebert](https://github.com/ferd), [Honeycomb](https://www.honeycomb.io/)
- [Greg Mefford](https://github.com/GregMefford), [STORD](https://www.stord.com/)
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
_Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/master/community-membership.md#maintainer)._
### Thanks to all the people who have contributed
[![contributors](https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-erlang)](https://github.com/open-telemetry/opentelemetry-erlang/graphs/contributors)

133
VERSIONING.md Normal file
View File

@ -0,0 +1,133 @@
# Versioning and Releasing
[OTP] Applications and the [OpenTelemetry Spec] itself use [semver v2].
In this document, references to OTP concepts are distinguished by capitalizing the word
(for example Application and Release) while the generic term (like release) is
lowercase.
[OTP]: http://erlang.org/doc/system_architecture_intro/sys_arch_intro.html
[OpenTelemetry Spec]: https://github.com/open-telemetry/opentelemetry-specification
[semver v2]: https://semver.org/spec/v2.0.0.html
## Module Prefix
The module prefix for all modules in any of these core Applications is
`otel`. This means modules can move between Applications without their name
changing. Because of Erlang's flat namespace, there is no code for a user to change
when an API graduates from experimental to stable, if the user was
using the latest version of the experimental API.
This also allows flexibility for modules that might be in the SDK but are found
to be better placed in the API, or vice versa. This has happened a few times in
the pre-1.0 world as functionality was floating from SDK to API at times.
## OTP Applications
### Experimental API (`opentelemetry_api_experimental`)
The experimental package is where any API that is not stable when 1.0 is
released [MUST] live. At this time (prior to 1.0) that means Metrics and Logging.
This package will always be 0.x because it is never stable and modules will be
removed when they are moved to the stable API package. Breaking changes,
as well as non-trivial additions, to the experimental API will only result in a
minor version bump.
[MUST]: https://tools.ietf.org/html/rfc2119#section-1
### API (`opentelemetry_api`)
The API package must provide semver-defined backwards-compatibility
once a major version (e.g. 1.0.0) is released. When a particular part of the API
becomes stable, its modules are moved from `opentelemetry_api_experimental` to
`opentelemetry_api` and a new minor release of both is published.
At the release of version 1.0, the following signal APIs will be included
in `opentelemetry_api`:
* Tracing
* Baggage
* Context
### Experimental SDK (`opentelemetry_sdk_experimental`)
The experimental SDK contains the implementations for the APIs in the
experimental API of the same minor version. For example, there may be
multiple patch-level releases (`v0.3.2`, `v0.3.3`) of the experimental
SDK for each minor version of the experimental API (`v0.3.0`).
Any setup for signals contained in the experimental SDK must be done on startup
of the experimental SDK. For example, setting the default Meter would be done
in `start/2` of `opentelemetry_sdk_experimental`.
### SDK (`opentelemetry`)
Functionality is implemented in this Application and the API is dynamically
configured to use a particular SDK -- at this time there is only 1 SDK
implementation, the default implementation.
A goal is that the latest SDK can always be used with any version of the API, so
that a user can always pull the latest implementation into their final Release
to run with any API versions that were used in instrumented Applications within the
Release.
### OTLP Exporter (`opentelemetry_exporter`)
Exporter implementations are tied to the SDK's public API.
## Releases
### Experimental API
As noted in the previous section, `opentelemetry_api_experimental` is versioned
separately from the rest and will always remain 0.x.
### API
Additions to the API are released with minor version bumps.
### Experimental SDK
As noted in the previous section, `opentelemetry_sdk_experimental` is versioned
separately from the rest, but in lockstep with `opentelemetry_api_experimental`,
and will always remain 0.x.
### SDK
Additions to the SDK are released with minor version bumps.
## Deprecation
Code is only marked as deprecated when the replacement is stable.
Unlikely example: There is a Tracing v2 spec defined. The module will be named
`otel_trace2` and the functions in `otel_trace` marked as deprecated.
Deprecated functions must be marked with `-deprecated` in the module so that
`xref` provides a warning about usage to the user.
## Removal
A major version bump is required to remove a signal or module.
In the unlikely example mentioned in the Deprecation section, this step would mean removal of the
original module (`otel_trace`) and a major version bump release.
## Examples
Purely for illustration purposes, not intended to represent actual releases:
- v1.0.0 release:
- `opentelemetry_api` 1.0.0
- Contains APIs for tracing, baggage, propagators
- `opentelemetry_api_experimental` 0.2.0
- Contains APIs for metrics
- `opentelemetry_sdk` 1.0.0
- `opentelemetry_sdk_experimental` 0.2.0
- v1.15.0 release (with metrics)
- `opentelemetry_api` 1.15.0
- Contains APIs for tracing, baggage, propagators, metrics
- `opentelemetry_api_experimental` 0.42.0
- No longer contains APIs for metrics
- `opentelemetry_sdk` 1.15.0
- `opentelemetry_sdk_experimental` 0.42.0

201
apps/opentelemetry/LICENSE Normal file
View File

@ -0,0 +1,201 @@
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
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,245 @@
# Erlang/Elixir OpenTelemetry SDK
[![Hex.pm](https://img.shields.io/hexpm/v/opentelemetry?label=SDK&style=for-the-badge)](https://hex.pm/packages/opentelemetry)
[![EEF Observability WG
project](https://img.shields.io/badge/EEF-Observability-black?style=for-the-badge)](https://github.com/erlef/eef-observability-wg)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/open-telemetry/opentelemetry-erlang/Erlang?style=for-the-badge)](https://github.com/open-telemetry/opentelemetry-erlang/actions)
The [SDK](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/sdk.md) is an implementation of the [OpenTelemetry
API](https://hex.pm/packages/opentelemetry_api) and should be included in your
final deployable artifact (usually an OTP Release).
## Configuration
The SDK starts up its supervision tree on boot, so initial configuration must be
done through the Application or [OS environment
variables](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/sdk-configuration.md).
The following example configurations show configuring the SDK to use the batch
span processor which then exports through the [OpenTelemetry
Protocol](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/protocol/otlp.md)
over HTTP to `http://localhost:4318`, encoding the Spans with protobufs.
```erlang
[
{opentelemetry,
[{span_processor, batch},
{traces_exporter, otlp}]},
{opentelemetry_exporter,
[{otlp_protocol, http_protobuf},
{otlp_endpoint, "http://localhost:4318"}]}]}
].
```
```elixir
config :opentelemetry,
span_processor: :batch,
traces_exporter: :otlp
config :opentelemetry_exporter,
otlp_protocol: :http_protobuf,
otlp_endpoint: "http://localhost:4318"
```
If your exporting pipeline is not ready, you may disable trace exporting to prevent memory overflows.
This can be done by setting `traces_exporter`'s value to the atom `none`.
```erlang
[
{opentelemetry,
[{traces_exporter, none}]}
].
```
```elixir
config :opentelemetry, traces_exporter: :none
```
The following sections detail the available SDK options and how to configure
them through either the OS or Application environment.
### Automatically Created Tracers
Spans are created by Tracers and each Tracer is associated with a [name and
version](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#get-a-tracer).
The name and version can be anything, but the macros provided by the API will always use
a Tracer with name/version of the OTP Application the macro is used in. To
facilitate this a Tracer is created for each available Application when the SDK
boots. It relies on mapping modules to Applications, so if there is a huge
number of modules in a Release the time to create all these Tracers can become
more than you want to wait on boot.
| OS | Application | Default | Type |
|:--------------------------------|:---------------------------|:--------|:--------|
| OTEL_CREATE_APPLICATION_TRACERS | create_application_tracers | true | boolean |
Disabling the creation of Tracers at start-up means when the macros are used to
start Spans the name and version of the Tracer creating those Spans will be
undefined, but everything will continue to work as before.
### Samplers
Sampling is a mechanism to control the number of traces collected and sent to the backend. A [Sampler](https://opentelemetry.io/docs/reference/specification/trace/sdk/#sampler) is responsible for making a decision on whether to sample a trace or not.
This decision happens when starting a span. For this reason, only the initial attributes passed to `with_span` or `start_span` are available to the Sampler. Attributes added within `with_span` or between `start_span` and `end_span` calls don't affect the outcome as the decision to sample or not has already been made.
There are several [built-in samplers](https://opentelemetry.io/docs/reference/specification/trace/sdk/#built-in-samplers) available, and it's possible to create custom samplers.
| OS | Application | Default | Type |
|:-------------------------------|:-------------------------|:----------|:--------|
| OTEL_TRACES_SAMPLER | sampler | parentbased_always_on | always_on, always_off, traceidratio, parentbased_always_on, parentbased_always_off, parentbased_traceidratio |
| OTEL_TRACES_SAMPLER_ARG | sampler | | String. Each Sampler type defines its own expected input, if any.|
#### Custom Sampler
To create a custom sampler, implement a module with behaviour `otel_sampler`, and then install your custom sampler when configuring the `opentelemetry` application
```elixir
defmodule MySampler do
require OpenTelemetry.Tracer, as: Tracer
@behaviour :otel_sampler
@impl :otel_sampler
def setup(_sampler_opts) do
[]
end
@impl :otel_sampler
def description(_sampler_config) do
"MySampler"
end
@impl :otel_sampler
def should_sample(
ctx,
_trace_id,
_links,
_span_name,
_span_kind,
_attributes,
_sampler_config
) do
sample_decision = ... # custom logic to determine whether to sample or not
tracestate = Tracer.current_span_ctx(ctx) |> OpenTelemetry.Span.tracestate()
case sample_decision do
true -> {:record_and_sample, [], tracestate}
false -> {:drop, [], tracestate}
end
end
end
```
```elixir
config :opentelemetry,
sampler: {:parent_based, %{root: {MySampler, %{my_config_arg: 1}}}},
span_processor: :batch,
traces_exporter: :otlp
```
### Propagators
Propagators define how to inject and extract context in requests to or from
external services. A propagator that works on key/value pairs of text, like HTTP
headers, can be any module that implements the `otel_propagator_text_map`
behaviour. There are 4 built-in propagators that are part of the API:
- [tracecontext](https://w3c.github.io/trace-context/): Encodes the Trace
context as headers `traceparent` and `tracestate`.
- [baggage](https://w3c.github.io/baggage/): Encodes
[baggage](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/baggage/api.md)
elements as a comma delimited list under header key `baggage`.
- [b3multi](https://github.com/openzipkin/b3-propagation#multiple-headers): The
propagation format from [Zipkin](https://zipkin.io/) that breaks the context across multiple
headers, `X-B3-TraceId`, `X-B3-SpanId` and `X-B3-Sampled`.
- [b3](https://github.com/openzipkin/b3-propagation#single-header): The
propagation format from Zipkin that encodes to a single header `b3`.
| OS | Application | Default | Type |
|:-----------------|:---------------------|:-----------------------|:-----------------------------------------------------------------|
| OTEL_PROPAGATORS | text_map_propagators | [tracecontext,baggage] | List of propagators (`tracecontext`, `baggage`, `b3multi`, `b3`) |
### Batch Span Processor
[Span
processors](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#span-processor)
are invoked when a Span is started and when it ends. The default processor is
the batch processor (`otel_batch_processor`) -- also available is the simple
processor (`otel_simple_processor`) which blocks on every finished Span until it
is exported.
The batch processor waits `bsp_scheduled_delay_ms` milliseconds or until the buffer of
finished Spans reaches `bsp_max_queue_size` and then exports the spans together.
The export is canceled if it takes longer than `bsp_exporting_timeout_ms`.
| OS | Application | Default | Type |
|:-------------------------------|:-------------------------|:--------|:--------|
| OTEL_BSP_SCHEDULE_DELAY_MILLIS | bsp_scheduled_delay_ms | 5000 | integer |
| OTEL_BSP_EXPORT_TIMEOUT_MILLIS | bsp_exporting_timeout_ms | 30000 | integer |
| OTEL_BSP_MAX_QUEUE_SIZE | bsp_max_queue_size | 2048 | integer |
### Resource Detectors
[Resources](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/overview.md#resources)
capture information about the environment the program is running in. For
example, a process producing telemetry that is running in a container on
Kubernetes has a Pod name, it is in a namespace and possibly is part of a
Deployment which also has a name. All three of these attributes can be included
in the Resource.
| OS | Application | Default | Type |
|:-------------------------------|:--------------------------|:-----------------------------------------------|:----------------|
| OTEL_RESOURCE_DETECTORS | resource_detectors | [otel_resource_env_var, otel_resource_app_env] | list of modules |
| OTEL_RESOURCE_DETECTOR_TIMEOUT | resource_detector_timeout | 5000 | integer |
The default detectors read resource attributes from the OS environment variable
`OTEL_RESOURCE_ATTRIBUTES` and Application environment variable `resource`.
### Span Limits
The number of Attributes, Events and Links on a Span are limited, as well as the
length of an Attribute's value. When the limit is reached any additional
Attributes, Events or Links are dropped and Attribute values larger than the
length limit are truncated.
| OS | Application | Default | Type |
|:---------------------------------------|:-----------------------------|:---------|:------------------------|
| OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT | attribute_count_limit | 128 | integer |
| OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT | attribute_value_length_limit | infinity | integer \| infinity |
| OTEL_SPAN_EVENT_COUNT_LIMIT | event_count_limit | 128 | integer |
| OTEL_SPAN_LINK_COUNT_LIMIT | link_count_limit | 128 | integer |
| OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT | attribute_per_event_limit | 128 | integer |
| OTEL_LINK_ATTRIBUTE_COUNT_LIMIT | attribute_per_link_limit | 128 | integer |
Read more in the specification about [Span
limits](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#span-limits)
and [Attribute
limits](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/common/common.md#attribute-limits).
### Span Sweeper
Because of Erlang's "Let It Crash" philosophy it is possible that at some point
a Span will never have `end_span` called. To handle these cases the SDK includes
a process that will periodically check the active Span table for Spans that are
older than the `span_ttl` and will drop or end the Span depending on the
configured `strategy`. The `failed_attribute_and_end_span` strategy will add the
attribute `finished_by_sweeper` with value `true` to the Span before calling
`end_span`.
The sweeper's configuration is a map under environment key `sweeper`.
| OS | Application | Default | Type |
|:-------------------------------|:-------------|:---------|:-----------------------------------------------------------|
| OTEL_SPAN_SWEEPER_INTERVAL | interval | 600000 | integer \| infinity |
| OTEL_SPAN_SWEEPER_STRATEGY | strategy | drop | drop \| end_span \| failed_attribute_and_end_span \| fun/1 |
| OTEL_SPAN_SWEEPER_SPAN_TTL | span_ttl | 1800000 | integer \| infinity |
| OTEL_SPAN_SWEEPER_STORAGE_SIZE | storage_size | infinity | integer \| infinity |
## Contributing
Read OpenTelemetry project [contributing
guide](https://github.com/open-telemetry/community/blob/main/CONTRIBUTING.md)
for general information about the project.

View File

@ -0,0 +1,25 @@
{source_url, <<"https://github.com/open-telemetry/opentelemetry-erlang">>}.
{extras, [<<"apps/opentelemetry/README.md">>, <<"apps/opentelemetry/LICENSE">>, <<"VERSIONING.md">>]}.
{main, <<"readme">>}.
{proglang, erlang}.
{groups_for_modules, [
{'Span', [otel_span_ets,
otel_span_limits,
otel_span_sweeper]},
{'Span Processing', [otel_span_processor,
otel_simple_processor,
otel_batch_processor]},
{'Exporter', [otel_exporter,
otel_exporter_pid,
otel_exporter_stdout,
otel_exporter_tab]},
{'Resource', [otel_resource,
otel_resource_detector,
otel_resource_app_env,
otel_resource_env_var]},
{'Sampling', [otel_sampler,
otel_sampler_always_on,
otel_sampler_always_off,
otel_sampler_parent_based,
otel_sampler_trace_id_ratio_based]}
]}.

View File

@ -16,6 +16,6 @@
%% @end
%%%-------------------------------------------------------------------------
-define(NOT_RECORD, not_record).
-define(RECORD, record).
-define(RECORD_AND_SAMPLED, record_and_sampled).
-define(DROP, drop).
-define(RECORD_ONLY, record_only).
-define(RECORD_AND_SAMPLE, record_and_sample).

View File

@ -0,0 +1,85 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc
%% @end
%%%-------------------------------------------------------------------------
-record(span, {
%% 128 bit int trace id
trace_id :: opentelemetry:trace_id() | undefined | '_',
%% 64 bit int span id
span_id :: opentelemetry:span_id() | undefined | '$1',
tracestate = [] :: opentelemetry:tracestate() | '_',
%% 64 bit int parent span
parent_span_id :: opentelemetry:span_id() | undefined | '_',
%% name of the span
name :: unicode:unicode_binary() | atom() | '_',
%% Distinguishes between spans generated in a particular context. For example,
%% two spans with the same name may be distinguished using `client` (caller)
%% and `server` (callee) to identify queueing latency associated with the span.status
kind :: opentelemetry:span_kind() | undefined | '_',
start_time :: opentelemetry:timestamp() | '$2',
end_time :: opentelemetry:timestamp() | undefined | '_',
%% A set of attributes on the span.
attributes :: otel_attributes:t() | undefined | '_',
%% List of time-stamped events in the Span.
events :: otel_events:t() | '_',
%% links to spans in other traces
links :: otel_links:t() | '_',
%% An optional final status for this span.
status :: opentelemetry:status() | undefined | '_',
%% 8-bit integer, lowest bit is if it is sampled
trace_flags = 1 :: integer() | undefined | '_',
%% this field is not propagated and is only here as an implementation optimization
%% If true updates like adding events are done on the span. The same as if the
%% trace flags lowest bit is 1 but simply not propagated.
is_recording :: boolean() | undefined | '_',
instrumentation_scope :: opentelemetry:instrumentation_scope() | undefined | '_'
}).
-record(span_limits, {
attribute_count_limit = 128 :: integer(), %% Maximum allowed attribute count per span;
attribute_value_length_limit = infinity :: integer() | infinity, %% Maximum allowed attribute value length
event_count_limit = 128 :: integer(), %% Maximum allowed span event count
link_count_limit = 128 :: integer(), %% Maximum allowed span link count
attribute_per_event_limit = 128 :: integer(), %% Maximum allowed attribute per span event count
attribute_per_link_limit = 128 :: integer() %% Maximum allowed attribute per span link count
}).
-record(link, {
trace_id :: opentelemetry:trace_id(),
span_id :: opentelemetry:span_id(),
attributes :: otel_attributes:t(),
tracestate :: opentelemetry:tracestate()
}).
-record(event, {
system_time_native :: integer(),
name :: unicode:unicode_binary() | atom(),
attributes :: otel_attributes:t()
}).

View File

@ -0,0 +1,11 @@
{erl_opts, [debug_info]}.
{deps, [{opentelemetry_api, "~> 1.4.0"}]}.
{profiles,
[{docs, [{edoc_opts,
[
{doclet, edoc_doclet_chunks},
{layout, edoc_layout_chunks},
{preprocess, true},
{dir, "_build/default/lib/opentelemetry/doc"},
{subpackages, true}]}]}]}.

View File

@ -0,0 +1,21 @@
{application, opentelemetry,
[{description, "Implementation of stable OpenTelemetry signals"},
{vsn, "1.5.1"},
{registered, [
%% global tracer provider supervisor for use by the API
otel_tracer_provider_sup
]},
{mod, {opentelemetry_app, []}},
{applications,
[kernel,
stdlib,
opentelemetry_api
]},
{exclude_paths, ["rebar.lock"]},
{env, []},
{modules, []},
{doc, "doc"},
{licenses, ["Apache-2.0"]},
{links, [{"GitHub", "https://github.com/open-telemetry/opentelemetry-erlang"}]}
]}.

View File

@ -0,0 +1,70 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @private
%%%-------------------------------------------------------------------------
-module(opentelemetry_app).
-behaviour(application).
-export([start/2,
stop/1]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
start(_StartType, _StartArgs) ->
Config = otel_configuration:merge_with_os(
application:get_all_env(opentelemetry)),
%% set the global propagators for HTTP based on the application env
%% these get set even if the SDK is disabled
setup_text_map_propagators(Config),
SupResult = opentelemetry_sup:start_link(Config),
case Config of
#{sdk_disabled := true} ->
%% skip the rest if the SDK is disabled
SupResult;
_ ->
%% set global span limits record based on configuration
otel_span_limits:set(Config),
Resource = otel_resource_detector:get_resource(),
_ = otel_tracer_provider_sup:start(?GLOBAL_TRACER_PROVIDER_NAME, Resource, Config),
%% must be done after the supervisor starts so that otel_tracer_server is running
%% TODO: make this work with release upgrades. Currently if an application's version
%% changes the version in the tracer will not be updated.
create_loaded_application_tracers(Config),
SupResult
end.
stop(_State) ->
ok.
%% internal functions
setup_text_map_propagators(#{text_map_propagators := List}) ->
CompositePropagator = otel_propagator_text_map_composite:create(List),
opentelemetry:set_text_map_propagator(CompositePropagator).
create_loaded_application_tracers(#{create_application_tracers := true}) ->
%% TODO: filter out OTP apps that will not have any instrumentation
LoadedApplications = application:loaded_applications(),
opentelemetry:create_application_tracers(LoadedApplications),
ok;
create_loaded_application_tracers(_) ->
ok.

View File

@ -0,0 +1,64 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @private
%%%-------------------------------------------------------------------------
-module(opentelemetry_sup).
-behaviour(supervisor).
-export([start_link/1]).
-export([init/1]).
-define(SERVER, ?MODULE).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
start_link(Opts) ->
supervisor:start_link({local, ?SERVER}, ?MODULE, [Opts]).
init([#{sdk_disabled := true}]) ->
{ok, {#{}, []}};
init([Opts]) ->
SupFlags = #{strategy => one_for_one,
intensity => 1,
period => 5},
Detectors = #{id => otel_resource_detector,
start => {otel_resource_detector, start_link, [Opts]},
restart => permanent,
shutdown => 5000,
type => worker,
modules => [otel_resource_detector]},
TracerProviderSup = #{id => otel_tracer_provider_sup,
start => {otel_tracer_provider_sup, start_link, []},
restart => permanent,
shutdown => 5000,
type => supervisor,
modules => [otel_tracer_provider_sup]},
SpanSup = #{id => otel_span_sup,
start => {otel_span_sup, start_link, [Opts]},
type => supervisor,
restart => permanent,
shutdown => infinity,
modules => [otel_span_sup]},
%% `SpanSup' should be the last to shutdown so the ETS table lives until the end
%% the `TracerServer' process
ChildSpecs = [SpanSup, Detectors, TracerProviderSup],
{ok, {SupFlags, ChildSpecs}}.

View File

@ -0,0 +1,465 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc The Batch Span Processor implements the {@link otel_span_processor}
%% behaviour.
%%
%% It stores finished Spans in a ETS table buffer and exports
%% them on an interval or when the table reaches a maximum size.
%%
%% You can configure these timeouts:
%%
%% <ul>
%% <li>`exporting_timeout_ms': how long to let the exports run before killing.</li>
%% <li>`check_table_size_ms': timeout to check the size of the export table.</li>
%% <li>`scheduled_delay_ms': how often to trigger running the exporters.</li>
%% </ul>
%%
%% The size limit of the current table where finished spans are stored can
%% be configured with the `max_queue_size' option.
%% @end
%%%-----------------------------------------------------------------------
-module(otel_batch_processor).
-behaviour(gen_statem).
-behaviour(otel_span_processor).
-export([start_link/1,
on_start/3,
on_end/2,
force_flush/1,
report_cb/1,
%% deprecated
set_exporter/1,
set_exporter/2,
set_exporter/3]).
-export([init/1,
callback_mode/0,
idle/3,
exporting/3,
terminate/3]).
%% uncomment when OTP-23 becomes the minimum required version
%% -deprecated({set_exporter, 1, "set through the otel_tracer_provider instead"}).
%% -deprecated({set_exporter, 2, "set through the otel_tracer_provider instead"}).
%% -deprecated({set_exporter, 3, "set through the otel_tracer_provider instead"}).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include_lib("kernel/include/logger.hrl").
-include("otel_span.hrl").
-record(data, {exporter :: {module(), term()} | undefined,
exporter_config :: {module(), term()} | undefined | none,
resource :: otel_resource:t() | undefined,
handed_off_table :: atom() | undefined,
runner_pid :: pid() | undefined,
max_queue_size :: integer() | infinity,
exporting_timeout_ms :: integer(),
check_table_size_ms :: integer() | infinity,
scheduled_delay_ms :: integer(),
table_1 :: atom(),
table_2 :: atom(),
reg_name :: atom()}).
-define(CURRENT_TABLES_KEY(Name), {?MODULE, current_table, Name}).
%% create unique table names to support multiple batch processors at once
-define(TABLE_NAME(TN), lists:concat([TN, "_", erlang:pid_to_list(self())])).
-define(TABLE_1, ?REG_NAME(?TABLE_NAME(otel_export_table1))).
-define(TABLE_2, ?REG_NAME(?TABLE_NAME(otel_export_table2))).
-define(CURRENT_TABLE(RegName), persistent_term:get(?CURRENT_TABLES_KEY(RegName))).
-define(DEFAULT_MAX_QUEUE_SIZE, 2048).
-define(DEFAULT_SCHEDULED_DELAY_MS, timer:seconds(5)).
-define(DEFAULT_EXPORTER_TIMEOUT_MS, timer:seconds(30)).
-define(DEFAULT_CHECK_TABLE_SIZE_MS, timer:seconds(1)).
-define(ENABLED_KEY(RegName), {?MODULE, enabled_key, RegName}).
-ifdef(TEST).
-export([current_tab_to_list/1]).
current_tab_to_list(RegName) ->
ets:tab2list(?CURRENT_TABLE(RegName)).
-endif.
%% require a unique name to distinguish multiple batch processors while
%% still having a single name, instead of a possibly changing pid, to
%% communicate with the processor
%% @doc Starts a Batch Span Processor.
%% @end
-spec start_link(#{name := atom() | list()}) -> {ok, pid(), map()}.
start_link(Config=#{name := Name}) ->
RegisterName = ?REG_NAME(Name),
Config1 = Config#{reg_name => RegisterName},
{ok, Pid} = gen_statem:start_link({local, RegisterName}, ?MODULE, [Config1], []),
{ok, Pid, Config1}.
%% @deprecated Please use {@link otel_tracer_provider}
set_exporter(Exporter) ->
set_exporter(global, Exporter, []).
%% @deprecated Please use {@link otel_tracer_provider}
-spec set_exporter(module(), term()) -> ok.
set_exporter(Exporter, Options) ->
gen_statem:call(?REG_NAME(global), {set_exporter, {Exporter, Options}}).
%% @deprecated Please use {@link otel_tracer_provider}
-spec set_exporter(atom(), module(), term()) -> ok.
set_exporter(Name, Exporter, Options) ->
gen_statem:call(?REG_NAME(Name), {set_exporter, {Exporter, Options}}).
%% @private
-spec on_start(otel_ctx:t(), opentelemetry:span(), otel_span_processor:processor_config())
-> opentelemetry:span().
on_start(_Ctx, Span, _) ->
Span.
%% @private
-spec on_end(opentelemetry:span(), otel_span_processor:processor_config())
-> true | dropped | {error, invalid_span} | {error, no_export_buffer}.
on_end(#span{trace_flags=TraceFlags}, _) when not(?IS_SAMPLED(TraceFlags)) ->
dropped;
on_end(Span=#span{}, #{reg_name := RegName}) ->
do_insert(RegName, Span);
on_end(_Span, _) ->
{error, invalid_span}.
%% @private
-spec force_flush(#{reg_name := gen_statem:server_ref()}) -> ok.
force_flush(#{reg_name := RegName}) ->
gen_statem:cast(RegName, force_flush).
%% @private
init([Args=#{reg_name := RegName}]) ->
process_flag(trap_exit, true),
SizeLimit = maps:get(max_queue_size, Args, ?DEFAULT_MAX_QUEUE_SIZE),
ExportingTimeout = maps:get(exporting_timeout_ms, Args, ?DEFAULT_EXPORTER_TIMEOUT_MS),
ScheduledDelay = maps:get(scheduled_delay_ms, Args, ?DEFAULT_SCHEDULED_DELAY_MS),
CheckTableSize = maps:get(check_table_size_ms, Args, ?DEFAULT_CHECK_TABLE_SIZE_MS),
%% TODO: this should be passed in from the tracer server
Resource = case maps:find(resource, Args) of
{ok, R} ->
R;
error ->
otel_resource_detector:get_resource()
end,
%% Resource = otel_tracer_provider:resource(),
Table1 = ?TABLE_1,
Table2 = ?TABLE_2,
_Tid1 = new_export_table(Table1),
_Tid2 = new_export_table(Table2),
persistent_term:put(?CURRENT_TABLES_KEY(RegName), Table1),
%% only enable export table if there is going to be an exporter
case maps:get(exporter, Args, none) of
ExporterConfig when ExporterConfig =:= none ; ExporterConfig =:= undefined ->
disable(RegName);
ExporterConfig ->
enable(RegName)
end,
{ok, idle, #data{exporter=undefined,
exporter_config=ExporterConfig,
resource = Resource,
handed_off_table=undefined,
max_queue_size=SizeLimit,
exporting_timeout_ms=ExportingTimeout,
check_table_size_ms=CheckTableSize,
scheduled_delay_ms=ScheduledDelay,
table_1=Table1,
table_2=Table2,
reg_name=RegName}}.
%% @private
callback_mode() ->
[state_functions, state_enter].
%% @private
idle(enter, _OldState, Data=#data{exporter=undefined,
exporter_config=ExporterConfig,
scheduled_delay_ms=SendInterval,
check_table_size_ms=CheckInterval,
reg_name=RegName}) ->
Exporter = init_exporter(RegName, ExporterConfig),
{keep_state, Data#data{exporter=Exporter},
[{{timeout, export_spans}, SendInterval, export_spans},
{{timeout, check_table_size}, CheckInterval, check_table_size}]};
idle(enter, _OldState, #data{scheduled_delay_ms=SendInterval,
check_table_size_ms=CheckInterval}) ->
{keep_state_and_data,
[{{timeout, export_spans}, SendInterval, export_spans},
{{timeout, check_table_size}, CheckInterval, check_table_size}]};
idle(_, export_spans, Data=#data{exporter=undefined,
exporter_config=ExporterConfig,
reg_name=RegName}) ->
Exporter = init_exporter(RegName, ExporterConfig),
{next_state, exporting, Data#data{exporter=Exporter}};
idle(_, export_spans, Data) ->
{next_state, exporting, Data};
idle(EventType, Event, Data) ->
handle_event_(idle, EventType, Event, Data).
%% receiving an `export_spans' timeout while exporting means the `ExportingTimeout'
%% is shorter than the `SendInterval'. Postponing the event will ensure we export
%% after
%% @private
exporting({timeout, export_spans}, export_spans, _) ->
{keep_state_and_data, [postpone]};
exporting(enter, _OldState, #data{exporter=undefined,
reg_name=RegName}) ->
%% exporter still undefined, go back to idle
%% first empty the table and disable the processor so no more spans are added
%% we wait until the attempt to export to disable so we don't lose spans
%% on startup but disable once it is clear an exporter isn't being set
clear_table_and_disable(RegName),
%% use state timeout to transition to `idle' since we can't set a
%% new state in an `enter' handler
{keep_state_and_data, [{state_timeout, 0, no_exporter}]};
exporting(enter, _OldState, Data=#data{exporting_timeout_ms=ExportingTimeout,
scheduled_delay_ms=SendInterval}) ->
case export_spans(Data) of
ok ->
%% in an `enter' handler we can't return a `next_state' or `next_event'
%% so we rely on a timeout to trigger the transition to `idle'
{keep_state, Data#data{runner_pid=undefined}, [{state_timeout, 0, empty_table}]};
{OldTableName, RunnerPid} ->
{keep_state, Data#data{runner_pid=RunnerPid,
handed_off_table=OldTableName},
[{state_timeout, ExportingTimeout, exporting_timeout},
{{timeout, export_spans}, SendInterval, export_spans}]}
end;
%% TODO: we need to just check if `exporter=undefined' right?
%% two hacks since we can't transition to a new state or send an action from `enter'
exporting(state_timeout, no_exporter, Data) ->
{next_state, idle, Data};
exporting(state_timeout, empty_table, Data) ->
{next_state, idle, Data};
exporting(state_timeout, exporting_timeout, Data=#data{handed_off_table=ExportingTable}) ->
%% kill current exporting process because it is taking too long
%% which deletes the exporting table, so create a new one and
%% repeat the state to force another span exporting immediately
Data1 = kill_runner(Data),
new_export_table(ExportingTable),
{next_state, idle, Data1};
%% important to verify runner_pid and FromPid are the same in case it was sent
%% after kill_runner was called but before it had done the unlink
exporting(info, {'EXIT', FromPid, _}, Data=#data{runner_pid=FromPid}) ->
complete_exporting(Data);
%% important to verify runner_pid and FromPid are the same in case it was sent
%% after kill_runner was called but before it had done the unlink
exporting(info, {completed, FromPid}, Data=#data{runner_pid=FromPid}) ->
complete_exporting(Data);
exporting(EventType, Event, Data) ->
handle_event_(exporting, EventType, Event, Data).
%% transition to exporting on a force_flush unless we are already exporting
%% if exporting then postpone the event so the force flush happens after
%% this current exporting is complete
handle_event_(exporting, _, force_flush, _Data) ->
{keep_state_and_data, [postpone]};
handle_event_(_State, _, force_flush, Data) ->
{next_state, exporting, Data};
handle_event_(_State, {timeout, check_table_size}, check_table_size, #data{max_queue_size=infinity}) ->
keep_state_and_data;
handle_event_(_State, {timeout, check_table_size}, check_table_size, #data{max_queue_size=MaxQueueSize,
check_table_size_ms=CheckInterval,
reg_name=RegName}) ->
case ets:info(?CURRENT_TABLE(RegName), size) of
M when M >= MaxQueueSize ->
disable(RegName);
_ ->
enable(RegName)
end,
{keep_state_and_data, [{{timeout, check_table_size}, CheckInterval, check_table_size}]};
handle_event_(_, {call, From}, {set_exporter, ExporterConfig}, Data=#data{exporter=OldExporter,
reg_name=RegName}) ->
otel_exporter:shutdown(OldExporter),
%% enable immediately or else spans will be dropped for a period even after this call returns
enable(RegName),
{keep_state, Data#data{exporter=undefined,
exporter_config=ExporterConfig}, [{reply, From, ok},
{next_event, internal, init_exporter}]};
handle_event_(_, internal, init_exporter, Data=#data{exporter=undefined,
exporter_config=ExporterConfig,
reg_name=RegName}) ->
Exporter = init_exporter(RegName, ExporterConfig),
{keep_state, Data#data{exporter=Exporter}};
handle_event_(_, _, _, _) ->
keep_state_and_data.
%% @private
terminate(_Reason, _State, #data{exporter=Exporter,
resource=Resource,
reg_name=RegName}) ->
CurrentTable = ?CURRENT_TABLE(RegName),
%% `export' is used to perform a blocking export
_ = export(Exporter, Resource, CurrentTable),
ok.
%%
init_exporter(RegName, ExporterConfig) ->
case otel_exporter:init(ExporterConfig) of
Exporter when Exporter =/= undefined andalso Exporter =/= none ->
enable(RegName),
Exporter;
_ ->
%% exporter is undefined/none
%% disable the insertion of new spans and delete the current table
clear_table_and_disable(RegName),
undefined
end.
clear_table_and_disable(RegName) ->
disable(RegName),
ets:delete(?CURRENT_TABLE(RegName)),
new_export_table(?CURRENT_TABLE(RegName)).
enable(RegName)->
persistent_term:put(?ENABLED_KEY(RegName), true).
disable(RegName) ->
persistent_term:put(?ENABLED_KEY(RegName), false).
is_enabled(RegName) ->
persistent_term:get(?ENABLED_KEY(RegName), true).
do_insert(RegName, Span) ->
try
case is_enabled(RegName) of
true ->
ets:insert(?CURRENT_TABLE(RegName), Span);
_ ->
dropped
end
catch
error:badarg ->
{error, no_batch_span_processor};
_:_ ->
{error, other}
end.
complete_exporting(Data=#data{handed_off_table=ExportingTable})
when ExportingTable =/= undefined ->
new_export_table(ExportingTable),
{next_state, idle, Data#data{runner_pid=undefined,
handed_off_table=undefined}};
complete_exporting(Data) ->
{next_state, idle, Data#data{runner_pid=undefined,
handed_off_table=undefined}}.
kill_runner(Data=#data{runner_pid=RunnerPid}) when RunnerPid =/= undefined ->
Mon = erlang:monitor(process, RunnerPid),
erlang:unlink(RunnerPid),
erlang:exit(RunnerPid, kill),
%% Wait for the runner process termination to be sure that
%% the export table is destroyed and can be safely recreated
receive
{'DOWN', Mon, process, RunnerPid, _} ->
Data#data{runner_pid=undefined, handed_off_table=undefined}
end.
new_export_table(Name) ->
ets:new(Name, [public,
named_table,
{write_concurrency, true},
duplicate_bag,
%% OpenTelemetry exporter protos group by the
%% instrumentation_scope. So using instrumentation_scope
%% as the key means we can easily lookup all spans for
%% for each instrumentation_scope and export together.
{keypos, #span.instrumentation_scope}]).
export_spans(#data{exporter=Exporter,
resource=Resource,
table_1=Table1,
table_2=Table2,
reg_name=RegName}) ->
CurrentTable = ?CURRENT_TABLE(RegName),
case ets:info(CurrentTable, size) of
0 ->
%% nothing to do if the table is empty
ok;
_ ->
NewCurrentTable = case CurrentTable of
Table1 ->
Table2;
Table2 ->
Table1
end,
%% an atom is a single word so this does not trigger a global GC
persistent_term:put(?CURRENT_TABLES_KEY(RegName), NewCurrentTable),
%% set the table to accept inserts
enable(RegName),
Self = self(),
RunnerPid = erlang:spawn_link(fun() -> send_spans(Self, Resource, Exporter) end),
ets:give_away(CurrentTable, RunnerPid, export),
{CurrentTable, RunnerPid}
end.
send_spans(FromPid, Resource, Exporter) ->
receive
{'ETS-TRANSFER', Table, FromPid, export} ->
export(Exporter, Resource, Table),
ets:delete(Table),
completed(FromPid)
end.
completed(FromPid) ->
FromPid ! {completed, self()}.
export(undefined, _, _) ->
true;
export(Exporter, Resource, SpansTid) ->
%% don't let a exporter exception crash us
%% and return true if exporter failed
try
otel_exporter_traces:export(Exporter, SpansTid, Resource) =:= failed_not_retryable
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => exporter,
during => export,
kind => Kind,
reason => Reason,
exporter => Exporter,
stacktrace => StackTrace}, #{report_cb => fun ?MODULE:report_cb/1}),
true
end.
%% logger format functions
%% @private
report_cb(#{source := exporter,
during := export,
kind := Kind,
reason := Reason,
exporter := {ExporterModule, _},
stacktrace := StackTrace}) ->
{"span exporter threw exception: exporter=~p ~ts",
[ExporterModule, otel_utils:format_exception(Kind, Reason, StackTrace)]}.

View File

@ -0,0 +1,544 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% Merges environment variable configuration values with application
%% configuration. The OS environment variables take precedence over the
%% application environment.
%% @private
%%%-------------------------------------------------------------------------
-module(otel_configuration).
-export([merge_with_os/1,
merge_list_with_environment/3,
report_cb/1]).
-define(BATCH_PROCESSOR_DEFAULTS, #{scheduled_delay_ms => 5000,
exporting_timeout_ms => 30000,
max_queue_size => 2048,
exporter => {opentelemetry_exporter, #{}}}).
-define(SIMPLE_PROCESSOR_DEFAULTS, #{exporting_timeout_ms => 30000,
exporter => {opentelemetry_exporter, #{}}}).
%% required configuration
%% using a map instead of a record because there can be more values
-type t() :: #{sdk_disabled := boolean(),
log_level := atom(),
register_loaded_applications := boolean() | undefined,
create_application_tracers := boolean() | undefined,
id_generator := module(),
deny_list := [atom()],
resource_detectors := [module()],
resource_detector_timeout := integer(),
bsp_scheduled_delay_ms := integer() | undefined,
bsp_exporting_timeout_ms := integer() | undefined,
bsp_max_queue_size := integer() | undefined,
ssp_exporting_timeout_ms := integer() | undefined,
text_map_propagators := [atom()],
traces_exporter := {atom(), term()} | none | undefined,
metrics_exporter := {atom(), term()} | none | undefined,
views := list(), %% TODO: type should be `[otel_meter_server:view_config]'
%% when Metrics are moved out of the experimental app
readers := [#{id := atom(), module => module(), config => map()}],
exemplars_enabled := boolean(),
exemplar_filter := always_on | always_off | trace_based,
metric_producers := [{module(), term()}],
processors := list(),
sampler := {atom(), term()},
sweeper := #{interval => integer() | infinity,
strategy => atom() | fun(),
span_ttl => integer() | infinity,
storage_size => integer() | infinity},
attribute_count_limit := integer(),
attribute_value_length_limit := integer() | infinity,
event_count_limit := integer(),
link_count_limit := integer(),
attribute_per_event_limit := integer(),
attribute_per_link_limit := integer()}.
-export_type([t/0]).
-include_lib("kernel/include/logger.hrl").
-include_lib("opentelemetry_api/include/gradualizer.hrl").
-spec new() -> t().
new() ->
?assert_type(#{sdk_disabled => false,
log_level => info,
register_loaded_applications => undefined,
create_application_tracers => undefined,
id_generator => otel_id_generator,
deny_list => [],
resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 5000,
bsp_scheduled_delay_ms => undefined,
bsp_exporting_timeout_ms => undefined,
bsp_max_queue_size => undefined,
ssp_exporting_timeout_ms => undefined,
text_map_propagators => [trace_context, baggage],
traces_exporter => {opentelemetry_exporter, #{}},
metrics_exporter => {opentelemetry_exporter, #{}},
views => [],
readers => [],
exemplars_enabled => false,
exemplar_filter => trace_based,
metric_producers => [],
processors => [{otel_batch_processor, ?BATCH_PROCESSOR_DEFAULTS}],
sampler => {parent_based, #{root => always_on}},
sweeper => #{interval => timer:minutes(10),
strategy => drop,
span_ttl => timer:minutes(30),
storage_size => infinity},
attribute_count_limit => 128,
attribute_value_length_limit => infinity,
event_count_limit => 128,
link_count_limit => 128,
attribute_per_event_limit => 128,
attribute_per_link_limit => 128}, t()).
-spec merge_with_os(list()) -> t().
merge_with_os(AppEnv) ->
ConfigMap = new(),
lists:foldl(fun(F, Acc) ->
F(AppEnv, Acc)
end, ConfigMap, [fun span_limits/2,
fun general/2,
fun sampler/2,
fun processors/2,
fun sweeper/2]).
-spec span_limits(list(), t()) -> t().
span_limits(AppEnv, ConfigMap) ->
merge_list_with_environment(config_mappings(span_limits), AppEnv, ConfigMap).
-spec general(list(), t()) -> t().
general(AppEnv, ConfigMap) ->
Config = merge_list_with_environment(config_mappings(general_sdk), AppEnv, ConfigMap),
%% merge the old `register_loaded_applications' with the new config key
%% `create_application_tracers' that has replaced it
Config1 = maps:update_with(create_application_tracers,
fun(undefined) ->
%% `create_application_tracers' isn't set so update
%% with the `register_loaded_applications' value
%% or `true' if it too isn't set
case maps:get(register_loaded_applications, Config) of
undefined ->
true;
Bool ->
Bool
end;
(Bool) ->
Bool
end, Config),
?assert_type(Config1, t()).
-spec sweeper(list(), t()) -> t().
sweeper(AppEnv, ConfigMap=#{sweeper := DefaultSweeperConfig}) ->
AppEnvSweeper = proplists:get_value(sweeper, AppEnv, #{}),
%% convert sweeper config to a list to utilize the merge_list_with_environment function
SweeperConfig = merge_list_with_environment(config_mappings(sweeper),
maps:to_list(AppEnvSweeper),
DefaultSweeperConfig),
ConfigMap#{sweeper => SweeperConfig}.
-spec processors(list(), t()) -> t().
processors(AppEnv, ConfigMap) ->
SpanProcessors = case transform(span_processor, proplists:get_value(span_processor, AppEnv)) of
undefined ->
Processors = proplists:get_value(processors, AppEnv, maps:get(processors, ConfigMap)),
transform(span_processors, Processors);
SpanProcessor ->
case proplists:get_value(processors, AppEnv) of
undefined ->
ok;
_ ->
?LOG_INFO("both processors and span_processor set in configuration but "
"only one should be used. span_processor will be ignored.")
end,
[SpanProcessor]
end,
ProcessorsConfig = lists:map(fun({Name, Opts}) ->
Opts1 = merge_processor_config(Name, Opts, ConfigMap, AppEnv),
{Name, Opts1}
end, SpanProcessors),
ConfigMap#{processors := ProcessorsConfig}.
%% use the top level app env and os env configuration to set/override processor config values
merge_processor_config(otel_batch_processor, Opts, ConfigMap, AppEnv) ->
BatchEnvMapping = [{bsp_scheduled_delay_ms, scheduled_delay_ms},
{bsp_exporting_timeout_ms, exporting_timeout_ms},
{bsp_max_queue_size, max_queue_size},
{traces_exporter, exporter}],
maps:merge(?BATCH_PROCESSOR_DEFAULTS,
merge_processor_config_(BatchEnvMapping, Opts, ConfigMap, AppEnv));
merge_processor_config(otel_simple_processor, Opts, ConfigMap, AppEnv) ->
SimpleEnvMapping = [{ssp_exporting_timeout_ms, exporting_timeout_ms},
{traces_exporter, exporter}],
maps:merge(?SIMPLE_PROCESSOR_DEFAULTS,
merge_processor_config_(SimpleEnvMapping, Opts, ConfigMap, AppEnv));
merge_processor_config(_, Opts, _, _) ->
Opts.
merge_processor_config_(EnvMapping, Opts, ConfigMap, AppEnv) ->
Mappings = config_mappings(general_sdk),
lists:foldl(fun({K, V}, Acc) ->
case maps:get(K, ConfigMap, undefined) of
undefined ->
Acc;
Value ->
%% use default only if the config isn't found in Opts
%% but if the value in ConfigMap isn't the default use it
IsDefault = is_default(K, AppEnv, Mappings),
case (IsDefault andalso not maps:is_key(V, Opts)) orelse not IsDefault of
true ->
Acc#{V => Value};
false ->
Acc
end
end
end, Opts, EnvMapping).
%% return true if the user (through application or os environment) configured
%% a certain setting
is_default(Key, AppEnv, Mappings) ->
{OSVarName, Key, _TransformType} = lists:keyfind(Key, 2, Mappings),
not lists:keymember(Key, 1, AppEnv) andalso os:getenv(OSVarName) =:= false.
%% sampler configuration is unique since it has the _ARG that is a sort of
%% sub-configuration of the sampler config, and isn't a list.
-spec sampler(list(), t()) -> t().
sampler(AppEnv, ConfigMap) ->
OSVar = "OTEL_TRACES_SAMPLER",
Key = sampler,
Transform = sampler,
case os:getenv("OTEL_TRACES_SAMPLER") of
false ->
case proplists:get_value(Key, AppEnv) of
undefined ->
ConfigMap;
Sampler ->
update_config_map(OSVar, Key, Transform, Sampler, ConfigMap)
end;
OSEnvSampler->
SamplerTuple = {OSEnvSampler, os:getenv("OTEL_TRACES_SAMPLER_ARG")},
update_config_map(OSVar, Key, Transform, SamplerTuple, ConfigMap)
end.
%% requires `ConfigMap' contains every key and its default
%% will replace the defaults with the value from either the OS environment or application
%% environment, with the OS environment taking precedence.
-spec merge_list_with_environment([{OSVar, Key, Transform}], AppEnv, ConfigMap) -> ConfigMap
when OSVar :: string(),
Key :: atom(),
Transform :: atom(),
AppEnv :: [{atom(), term()}],
ConfigMap :: map().
merge_list_with_environment(ConfigMappings, AppEnv, ConfigMap) ->
lists:foldl(fun({OSVar, Key, Transform}, Acc) ->
case os:getenv(OSVar) of
false ->
%% not in the OS environment so check application environment
case lists:keyfind(Key, 1, AppEnv) of
false ->
%% not in the application env so leave default
Acc;
{_, Value} ->
%% transform even the value from the
%% application environment to ensure it
%% is of the right type/format
update_config_map(OSVar, Key, Transform, Value, Acc)
end;
OSVal ->
update_config_map(OSVar, Key, Transform, OSVal, Acc)
end
end, ConfigMap, ConfigMappings).
update_config_map(OSVar, Key, Transform, Value, ConfigMap) ->
try transform(Transform, Value) of
TransformedValue ->
ConfigMap#{Key := TransformedValue}
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => transform,
kind => Kind,
reason => Reason,
os_var => OSVar,
key => Key,
transform => Transform,
value => Value,
stacktrace => StackTrace},
#{report_cb => fun ?MODULE:report_cb/1}),
ConfigMap
end.
report_cb(#{source := transform,
kind := Kind,
reason := Reason,
os_var := OSVar,
key := Key,
transform := Transform,
value := Value,
stacktrace := StackTrace}) ->
{"Transforming configuration value failed: os_var=~ts key=~ts transform=~ts value=~ts exception=~ts",
[OSVar, Key, Transform, Value, otel_utils:format_exception(Kind, Reason, StackTrace)]}.
config_mappings(general_sdk) ->
[{"OTEL_SDK_DISABLED", sdk_disabled, boolean},
{"OTEL_LOG_LEVEL", log_level, existing_atom},
%% `register_loaded_applications' is kept for backwards compatibility
{"OTEL_REGISTER_LOADED_APPLICATIONS", register_loaded_applications, boolean},
{"OTEL_CREATE_APPLICATION_TRACERS", create_application_tracers, boolean},
{"OTEL_ID_GENERATOR", id_generator, existing_atom},
{"OTEL_DENY_LIST", deny_list, existing_atom_list},
{"OTEL_PROPAGATORS", text_map_propagators, propagators},
{"OTEL_TRACES_EXPORTER", traces_exporter, exporter},
{"OTEL_METRICS_EXPORTER", metrics_exporter, exporter},
{"OTEL_METRIC_VIEWS", views, views},
{"OTEL_METRIC_READERS", readers, readers},
{"OTEL_ERLANG_X_EXEMPLARS_ENABLED", exemplars_enabled, boolean},
{"OTEL_METRICS_EXEMPLAR_FILTER", exemplar_filter, exemplar_filter},
{"OTEL_ERLANG_X_METRIC_PRODUCERS", metric_producers, metric_producers},
{"OTEL_RESOURCE_DETECTORS", resource_detectors, existing_atom_list},
{"OTEL_RESOURCE_DETECTOR_TIMEOUT", resource_detector_timeout, integer},
{"OTEL_BSP_SCHEDULE_DELAY_MILLIS", bsp_scheduled_delay_ms, integer},
{"OTEL_BSP_EXPORT_TIMEOUT_MILLIS", bsp_exporting_timeout_ms, integer},
{"OTEL_BSP_MAX_QUEUE_SIZE", bsp_max_queue_size, integer},
%% the following is not supported yet
%% {"OTEL_BSP_MAX_EXPORT_BATCH_SIZE", bsp_max_export_batch_size, integer}
{"OTEL_SSP_EXPORT_TIMEOUT_MILLIS", ssp_exporting_timeout_ms, integer}
];
config_mappings(span_limits) ->
[{"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", attribute_count_limit, integer},
{"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", attribute_value_length_limit, integer_infinity},
{"OTEL_SPAN_EVENT_COUNT_LIMIT", event_count_limit, integer},
{"OTEL_SPAN_LINK_COUNT_LIMIT", link_count_limit, integer},
{"OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", attribute_per_event_limit, integer},
{"OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", attribute_per_link_limit, integer}%% ,
%% {"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", attribute_value_length_limit, integer},
%% {"OTEL_ATTRIBUTE_COUNT_LIMIT", attribute_per_link_limit, integer}
];
config_mappings(sweeper) ->
[{"OTEL_SPAN_SWEEPER_INTERVAL", interval, integer_infinity},
{"OTEL_SPAN_SWEEPER_STRATEGY", strategy, atom_or_fun},
{"OTEL_SPAN_SWEEPER_SPAN_TTL", span_ttl, integer_infinity},
{"OTEL_SPAN_SWEEPER_STORAGE_SIZE", storage_size, integer_infinity}
].
transform(_, undefined) ->
undefined;
transform(existing_atom_list, [A | _]=List) when is_atom(A) ->
List;
transform(existing_atom_list, String) when is_list(String) ->
List = string:split(String, ",", all),
lists:filtermap(fun(A) ->
try transform(existing_atom, string:trim(A)) of
Value ->
{true, Value}
catch
_:_ ->
false
end
end, List);
transform(exporter, Exporter) when Exporter =:= "otlp" ; Exporter =:= otlp ->
{opentelemetry_exporter, #{}};
transform(exporter, Exporter) when Exporter =:= "jaeger" ; Exporter =:= jaeger ->
?LOG_WARNING("configuring jaeger exporter through OTEL_TRACES_EXPORTER is not yet supported ", []),
none;
transform(exporter, Exporter) when Exporter =:= "zipkin" ; Exporter =:= zipkin ->
?LOG_WARNING("configuring zipkin exporter through OTEL_TRACES_EXPORTER is not yet supported ", []),
none;
transform(exporter, Exporter) when Exporter =:= "none" ; Exporter =:= none ->
none;
transform(exporter, Value={Term, _}) when is_atom(Term) ->
Value;
transform(exporter, UnknownExporter) when is_list(UnknownExporter) ->
?LOG_WARNING("unknown exporter ~p. falling back to default otlp", [UnknownExporter]),
{opentelemetry_exporter, #{}};
transform(otlp_protocol, Proto) when Proto =:= "grpc"; Proto =:= grpc ->
grpc;
transform(otlp_protocol, Proto) when Proto =:= "http/protobuf"; Proto =:= "http_protobuf"; Proto =:= http_protobuf ->
http_protobuf;
transform(otlp_protocol, Proto) when Proto =:= "http/json"; Proto =:= "http_json"; Proto =:= http_json ->
?LOG_WARNING("The http/json transport protocol is not supported by the OTLP exporter, spans will not be exported.", []),
undefined;
transform(otlp_protocol, Proto) ->
?LOG_WARNING("unknown ~ts transport protocol, spans will not be exported.", [Proto]),
undefined;
transform(integer_infinity, infinity) ->
infinity;
transform(integer_infinity, Value) ->
transform(integer, Value);
transform(integer, Value) when is_integer(Value) ->
Value;
transform(integer, Value) when is_list(Value) ->
list_to_integer(Value);
transform(existing_atom, Value) when is_atom(Value) ->
Value;
transform(existing_atom, Value) when is_list(Value) ->
list_to_existing_atom(Value);
transform(atom_or_fun, Value) when is_list(Value) ->
list_to_existing_atom(Value);
transform(atom_or_fun, Value) when is_atom(Value) ->
Value;
transform(atom_or_fun, Value) when is_function(Value) ->
Value;
transform(boolean, Value) when is_boolean(Value) ->
Value;
transform(boolean, "true") ->
true;
transform(boolean, "false") ->
false;
transform(url, Value=#{}) ->
Value;
transform(url, Value) ->
uri_string:parse(Value);
%% convert sampler string to usable configuration term
transform(sampler, {"parentbased_always_on", _}) ->
{parent_based, #{root => always_on}};
transform(sampler, {"parentbased_always_off", _}) ->
{parent_based, #{root => always_off}};
transform(sampler, {"always_on", _}) ->
always_on;
transform(sampler, {"always_off", _}) ->
always_off;
transform(sampler, {"traceidratio", false}) ->
{trace_id_ratio_based, 1.0};
transform(sampler, {"traceidratio", Probability}) ->
{trace_id_ratio_based, probability_string_to_float(Probability)};
transform(sampler, {"parentbased_traceidratio", false}) ->
{parent_based, #{root => {trace_id_ratio_based, 1.0}}};
transform(sampler, {"parentbased_traceidratio", Probability}) ->
{parent_based, #{root => {trace_id_ratio_based, probability_string_to_float(Probability)}}};
transform(sampler, Value) ->
Value;
transform(key_value_list, Value) when is_list(Value) ->
case io_lib:printable_unicode_list(Value) of
true ->
Pairs = string:split(Value, ",", all),
lists:filtermap(fun(Pair) ->
case string:split(Pair, "=", leading) of
[K, V] ->
V1 = re:replace(string:trim(V), "^\"|\"$", "", [global, {return, list}]),
{true, {string:trim(K), V1}};
_ ->
false
end
end, Pairs);
false ->
Value
end;
transform(propagators, [P | _]=Propagators) when is_atom(P) ->
lists:filtermap(fun(Propagator) ->
case transform(propagator, Propagator) of
undefined ->
false;
Value ->
{true, Value}
end
end, Propagators);
transform(propagators, PropagatorsString) when is_list(PropagatorsString) ->
Propagators = string:split(PropagatorsString, ",", all),
lists:filtermap(fun(Propagator) when is_list(Propagator) ->
case transform(propagator, string:trim(Propagator)) of
undefined ->
false;
Value ->
{true, Value}
end
end, Propagators);
transform(propagator, Value) when Value =:= "tracecontext" ;
Value =:= tracecontext ;
Value =:= trace_context ->
trace_context;
transform(propagator, Value) when Value =:= "baggage" ;
Value =:= baggage ->
baggage;
transform(propagator, Value) when Value =:= "b3multi" ;
Value =:= b3multi ->
b3multi;
transform(propagator, Value) when Value =:= "b3" ;
Value =:= b3 ->
b3;
%% TODO: support jager propagator format
%% transform(propagator, "jaeger") ->
%% jaeger;
transform(propagator, Propagator) when is_atom(Propagator) ->
Propagator;
transform(propagator, Propagator) ->
?LOG_WARNING("Ignoring unknown propagator ~ts in OS environment variable $OTEL_PROPAGATORS",
[Propagator]),
undefined;
transform(span_processors, Processors) when is_list(Processors) ->
[transform(span_processor, Processor) || Processor <- Processors];
transform(span_processors, Unknown) ->
?LOG_WARNING("processors value must be a list, but ~ts given. No span processors will be used", [Unknown]),
[];
transform(span_processor, batch) ->
{otel_batch_processor, ?BATCH_PROCESSOR_DEFAULTS};
transform(span_processor, simple) ->
{otel_simple_processor, ?SIMPLE_PROCESSOR_DEFAULTS};
transform(span_processor, SpanProcessor) ->
SpanProcessor;
transform(readers, Readers) ->
Readers;
transform(exemplar_filter, ExemplarFilter) when ExemplarFilter =:= "always_on" ;
ExemplarFilter =:= always_on ->
always_on;
transform(exemplar_filter, ExemplarFilter) when ExemplarFilter =:= "always_off" ;
ExemplarFilter =:= always_off ->
always_off;
transform(exemplar_filter, _) ->
trace_based;
transform(metric_producers, MetricProducers) when is_list(MetricProducers) ->
lists:filtermap(fun({ProducerModule, ProducerConfig}) when is_atom(ProducerModule) ->
{true, {ProducerModule, ProducerConfig}};
(ProducerModule) when is_atom(ProducerModule) ->
{true, {ProducerModule, []}};
(_) ->
false
end, MetricProducers);
transform(views, Views) ->
Views.
probability_string_to_float(Probability) ->
try list_to_float(Probability) of
Float ->
Float
catch
error:badarg when Probability =:= "1" ->
1.0;
error:badarg when Probability =:= "0" ->
0.0;
error:badarg ->
?LOG_WARNING("Unable to convert $OTEL_TRACE_SAMPLER_ARG string value ~ts to float, using 1.0"),
1.0
end.

View File

@ -0,0 +1,101 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc
%% @end
%%%-------------------------------------------------------------------------
-module(otel_events).
-export([new/3,
add/2,
list/1,
dropped/1]).
-include("otel_span.hrl").
-record(events, {
count_limit :: integer(),
attribute_per_event_limit :: integer(),
attribute_value_length_limit :: integer() | infinity,
dropped :: integer(),
list :: [#event{}]
}).
-type t() :: #events{}.
-export_type([t/0]).
new(EventCountLimit, AttributePerEventLimit, AttributeValueLengthLimit) ->
#events{count_limit=EventCountLimit,
attribute_per_event_limit=AttributePerEventLimit,
attribute_value_length_limit=AttributeValueLengthLimit,
dropped=0,
list=[]}.
add(NewEvents, Events) ->
add_events(NewEvents, Events).
list(#events{list=List}) ->
List.
dropped(#events{dropped=Dropped}) ->
Dropped.
%%
add_events(NewEvents, Events=#events{count_limit=CountLimit,
list=List}) ->
Limit = CountLimit - length(List),
add_events_(NewEvents, Limit, Events).
add_events_([], _, Events) ->
Events;
add_events_(NewEvents, Limit, Events=#events{dropped=Dropped}) when Limit =< 0->
%% we've hit the limit on the number of events so drop the rest
Events#events{dropped=Dropped + length(NewEvents)};
add_events_([NewEvent | Rest], Limit, Events=#events{attribute_per_event_limit=AttributePerEventLimit,
attribute_value_length_limit=AttributeValueLengthLimit,
dropped=Dropped,
list=List}) ->
case new_event(NewEvent, AttributePerEventLimit, AttributeValueLengthLimit) of
drop ->
add_events_(Rest, Limit, Events#events{dropped=Dropped + 1});
Event ->
add_events_(Rest, Limit - 1, Events#events{list=[Event | List]})
end.
new_event(#{system_time_native := Timestamp,
name := Name,
attributes := Attributes}, AttributePerEventLimit, AttributeValueLengthLimit) ->
#event{system_time_native=Timestamp,
name=Name,
attributes=otel_attributes:new(Attributes, AttributePerEventLimit, AttributeValueLengthLimit)};
new_event(#{name := Name,
attributes := Attributes}, AttributePerEventLimit, AttributeValueLengthLimit) ->
#event{system_time_native=opentelemetry:timestamp(),
name=Name,
attributes=otel_attributes:new(Attributes, AttributePerEventLimit, AttributeValueLengthLimit)};
new_event({Time, Name, Attributes}, AttributePerEventLimit, AttributeValueLengthLimit)
when is_binary(Name) ; is_atom(Name) ->
#event{system_time_native=Time,
name=Name,
attributes=otel_attributes:new(Attributes, AttributePerEventLimit, AttributeValueLengthLimit)};
new_event({Name, Attributes}, AttributePerEventLimit, AttributeValueLengthLimit)
when is_binary(Name) ; is_atom(Name) ->
#event{system_time_native=opentelemetry:timestamp(),
name=Name,
attributes=otel_attributes:new(Attributes, AttributePerEventLimit, AttributeValueLengthLimit)};
new_event(_, _, _) ->
drop.

View File

@ -0,0 +1,174 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc
%% @end
%%%-----------------------------------------------------------------------
-module(otel_exporter).
-export([init/1,
export_traces/4,
export_metrics/4,
export_logs/4,
export_traces/3,
export_metrics/3,
export_logs/3,
shutdown/1,
report_cb/1]).
%% Kept only for backwards compatibility. Look at `otel_exporter_traces', `otel_exporter_metrics'
%% and `otel_exporter_logs' instead.
-callback init(term()) -> {ok, term()} | ignore.
%% Kept only for backwards compatibility. Look at `otel_exporter_traces', `otel_exporter_metrics'
%% and `otel_exporter_logs' instead.
-callback export(traces | logs | metrics, ets:tab(), otel_resource:t(), term()) -> ok |
success |
failed_not_retryable |
failed_retryable.
%% Kept only for backwards compatibility. Look at `otel_exporter_traces', `otel_exporter_metrics'
%% and `otel_exporter_logs' instead.failed_retryable.
-callback shutdown(term()) -> ok.
-include_lib("kernel/include/logger.hrl").
init({ExporterModule, Config}) when is_atom(ExporterModule) ->
try ExporterModule:init(Config) of
{ok, ExporterState} when ExporterModule =:= opentelemetry_exporter ->
%% since we log when the initialization failed so the user knows it later succeeded
?LOG_INFO("OTLP exporter successfully initialized"),
{ExporterModule, ExporterState};
{ok, ExporterState} ->
?LOG_INFO("Exporter ~tp successfully initialized", [ExporterModule]),
{ExporterModule, ExporterState};
ignore ->
undefined
catch
Kind:Reason:StackTrace ->
%% logging in debug level since config argument in stacktrace could have secrets
?LOG_DEBUG(#{source => exporter,
during => init,
kind => Kind,
reason => Reason,
exporter => ExporterModule,
stacktrace => StackTrace}, #{report_cb => fun ?MODULE:report_cb/1}),
%% print a more useful message about the failure if we can discern
%% one from the failure reason and exporter used
case {Kind, Reason} of
{error, badarg} when ExporterModule =:= opentelemetry_exporter ->
case maps:get(protocol, Config, undefined) of
grpc ->
%% grpc protocol uses grpcbox which is not included by default
%% this will check if it is available so we can warn the user if
%% the dependency needs to be added
try grpcbox:module_info() of
_ ->
undefined
catch
_:_ ->
?LOG_WARNING("OTLP exporter failed to initialize when using the GRPC "
"protocol and `grpcbox` module is not available in the "
"code path. Verify that you have the `grpcbox` dependency "
"included and rerun.", []),
undefined
end;
_ ->
%% same as the debug log above
%% without the stacktrace and at a higher level
?LOG_WARNING(#{source => exporter,
during => init,
kind => Kind,
reason => Reason,
exporter => ExporterModule}, #{report_cb => fun ?MODULE:report_cb/1}),
undefined
end;
{error, undef} when ExporterModule =:= opentelemetry_exporter ->
?LOG_WARNING("OTLP exporter module `opentelemetry_exporter` not found. "
"Verify you have included the `opentelemetry_exporter` dependency."),
undefined;
{error, undef} ->
?LOG_WARNING("Exporter module ~tp not found. Verify you have included "
"the dependency that contains the exporter module.", [ExporterModule]),
undefined;
_ ->
%% same as the debug log above
%% without the stacktrace and at a higher level
?LOG_WARNING(#{source => exporter,
during => init,
kind => Kind,
reason => Reason,
exporter => ExporterModule}, #{report_cb => fun ?MODULE:report_cb/1}),
undefined
end
end;
init(Exporter) when Exporter =:= none ; Exporter =:= undefined ->
undefined;
init(ExporterModule) when is_atom(ExporterModule) ->
init({ExporterModule, []}).
export_traces({ExporterModule, Config}, SpansTid, Resource) ->
ExporterModule:export(traces, SpansTid, Resource, Config).
export_metrics({ExporterModule, Config}, MetricsTid, Resource) ->
ExporterModule:export(metrics, MetricsTid, Resource, Config).
export_logs({ExporterModule, Config}, Batch, Resource) ->
ExporterModule:export(logs, Batch, Resource, Config).
%% below export_* functions are for backwards compatibility
export_traces(ExporterModule, SpansTid, Resource, Config) ->
ExporterModule:export(traces, SpansTid, Resource, Config).
export_metrics(ExporterModule, MetricsTid, Resource, Config) ->
ExporterModule:export(metrics, MetricsTid, Resource, Config).
export_logs(ExporterModule, Batch, Resource, Config) ->
ExporterModule:export(logs, Batch, Resource, Config).
shutdown(undefined) ->
ok;
shutdown({ExporterModule, Config}) ->
ExporterModule:shutdown(Config).
report_cb(#{source := exporter,
during := init,
kind := Kind,
reason := Reason,
exporter := opentelemetry_exporter,
stacktrace := StackTrace}) ->
{"OTLP exporter failed to initialize: ~ts",
[otel_utils:format_exception(Kind, Reason, StackTrace)]};
report_cb(#{source := exporter,
during := init,
kind := Kind,
reason := Reason,
exporter := ExporterModule,
stacktrace := StackTrace}) ->
{"Exporter ~tp failed to initialize: ~ts",
[ExporterModule, otel_utils:format_exception(Kind, Reason, StackTrace)]};
report_cb(#{source := exporter,
during := init,
kind := Kind,
reason := Reason,
exporter := opentelemetry_exporter}) ->
{"OTLP exporter failed to initialize with exception ~tp:~tp", [Kind, Reason]};
report_cb(#{source := exporter,
during := init,
kind := Kind,
reason := Reason,
exporter := ExporterModule}) ->
{"Exporter ~p failed to initialize with exception ~tp:~tp", [ExporterModule, Kind, Reason]}.

View File

@ -12,12 +12,12 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% @doc A test reporter for sending trace spans to an Erlang PID as message.
%% @doc A test exporter for sending trace spans to an Erlang PID as message.
%% @end
%%%-----------------------------------------------------------------------
-module(ot_exporter_pid).
-module(otel_exporter_pid).
-behaviour(ot_exporter).
-behaviour(otel_exporter_traces).
-export([init/1,
export/3,

View File

@ -12,12 +12,12 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% @doc Reporter that prints spans to stdout.
%% @doc Exporter that prints spans to stdout.
%% @end
%%%-----------------------------------------------------------------------
-module(ot_exporter_stdout).
-module(otel_exporter_stdout).
-behaviour(ot_exporter).
-behaviour(otel_exporter_traces).
-export([init/1,
export/3,

View File

@ -15,9 +15,9 @@
%% @doc A test reporter that keeps finished spans in an ETS table.
%% @end
%%%-----------------------------------------------------------------------
-module(ot_exporter_tab).
-module(otel_exporter_tab).
-behaviour(ot_exporter).
-behaviour(otel_exporter_traces).
-export([init/1,
export/3,

View File

@ -15,7 +15,11 @@
%% @doc
%% @end
%%%-----------------------------------------------------------------------
-module(ot_exporter).
-module(otel_exporter_traces).
-export([init/1,
export/3,
shutdown/1]).
%% Do any initialization of the exporter here and return configuration
%% that will be passed along with a list of spans to the `export' function.
@ -25,8 +29,17 @@
%% spans that have been collected so far and the configuration returned in `init'.
%% Do whatever needs to be done to export each span here, the caller will block
%% until it returns.
-callback export(ets:tab(), ot_resource:t(), term()) -> ok |
success |
failed_not_retryable |
failed_retryable.
-callback export(ets:tab(), otel_resource:t(), term()) -> ok |
success |
failed_not_retryable |
failed_retryable.
-callback shutdown(term()) -> ok.
init(Opts) ->
otel_exporter:init(Opts).
export({ExporterModule, Config}, SpansTid, Resource) ->
ExporterModule:export(SpansTid, Resource, Config).
shutdown(Exporter) ->
otel_exporter:shutdown(Exporter).

View File

@ -0,0 +1,56 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc This module provides the behaviour to implement for custom trace
%% and span id generation and the default implementation of the
%% generators which produces random 128 bit and 64 bit integers for the
%% trace id and span id.
%% @end
%%%-----------------------------------------------------------------------
-module(otel_id_generator).
-export([generate_trace_id/0,
generate_trace_id/1,
generate_span_id/0,
generate_span_id/1]).
-callback generate_trace_id() -> opentelemetry:trace_id().
-callback generate_span_id() -> opentelemetry:span_id().
-type t() :: module().
-export_type([t/0]).
-include_lib("opentelemetry_api/include/gradualizer.hrl").
%% @doc Calls a module implementing the `otel_id_generator' behaviour to generate a trace id
-spec generate_trace_id(t()) -> opentelemetry:trace_id().
generate_trace_id(Module) ->
Module:generate_trace_id().
%% @doc Calls a module implementing the `otel_id_generator' behaviour to generate a span id
-spec generate_span_id(t()) -> opentelemetry:span_id().
generate_span_id(Module) ->
Module:generate_span_id().
%% @doc Generates a 128 bit random integer to use as a trace id.
-spec generate_trace_id() -> opentelemetry:trace_id().
generate_trace_id() ->
rand:uniform(?assert_type(2 bsl 127 - 1, pos_integer())). %% 2 shifted left by 127 == 2 ^ 128
%% @doc Generates a 64 bit random integer to use as a span id.
-spec generate_span_id() -> opentelemetry:span_id().
generate_span_id() ->
rand:uniform(?assert_type(2 bsl 63 - 1, pos_integer())). %% 2 shifted left by 63 == 2 ^ 64

View File

@ -0,0 +1,104 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc
%% @end
%%%-------------------------------------------------------------------------
-module(otel_links).
-export([new/4,
list/1,
dropped/1]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_span.hrl").
-record(links, {
count_limit :: integer(),
attribute_per_link_limit :: integer(),
attribute_value_length_limit :: integer() | infinity,
dropped :: integer(),
list :: [#link{}]
}).
-type t() :: #links{}.
-export_type([t/0]).
new(List, LinkCountLimit, AttributePerLinkLimit, AttributeValueLengthLimit) ->
{Links, Dropped} = create_links(List, LinkCountLimit, AttributePerLinkLimit, AttributeValueLengthLimit),
#links{count_limit=LinkCountLimit,
attribute_per_link_limit=AttributePerLinkLimit,
attribute_value_length_limit=AttributeValueLengthLimit,
dropped=Dropped,
list=Links}.
list(#links{list=List}) ->
List.
dropped(#links{dropped=Dropped}) ->
Dropped.
%%
create_links(List, LinkCountLimit, AttributePerLinkLimit, AttributeValueLengthLimit) ->
create_links(List, LinkCountLimit, AttributePerLinkLimit, AttributeValueLengthLimit, 0, []).
create_links([], _, _, _AttributeValueLengthLimit, Dropped, Links) ->
{Links, Dropped};
create_links(List, 0, _, _, Dropped, Links) ->
{Links, Dropped + length(List)};
create_links([L | Rest], Limit, AttributePerLinkLimit, AttributeValueLengthLimit, Dropped, List) ->
case new_link(L, AttributePerLinkLimit, AttributeValueLengthLimit) of
drop ->
create_links(Rest, Limit, AttributePerLinkLimit, AttributeValueLengthLimit, Dropped + 1, List);
Link ->
create_links(Rest, Limit - 1, AttributePerLinkLimit, AttributeValueLengthLimit, Dropped, [Link | List])
end.
%%
new_link({TraceId, SpanId, Attributes, TraceState}, AttributePerLinkLimit, AttributeValueLengthLimit)
when is_integer(TraceId),
is_integer(SpanId),
(is_list(Attributes) orelse is_map(Attributes)) ->
#link{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
attributes=otel_attributes:new(Attributes, AttributePerLinkLimit, AttributeValueLengthLimit)};
new_link(Link=#link{}, _AttributePerLinkLimit, _AttributeValueLengthLimit) ->
Link;
new_link(#{trace_id := TraceId,
span_id := SpanId,
tracestate := TraceState,
attributes := Attributes}, AttributePerLinkLimit, AttributeValueLengthLimit) ->
#link{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
attributes=otel_attributes:new(Attributes, AttributePerLinkLimit, AttributeValueLengthLimit)};
new_link({#span_ctx{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState}, Attributes}, AttributePerLinkLimit, AttributeValueLengthLimit) ->
#link{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
attributes=otel_attributes:new(Attributes, AttributePerLinkLimit, AttributeValueLengthLimit)};
new_link(#span_ctx{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState}, AttributePerLinkLimit, AttributeValueLengthLimit) ->
#link{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
attributes=otel_attributes:new([], AttributePerLinkLimit, AttributeValueLengthLimit)};
new_link(_, _, _) ->
drop.

View File

@ -0,0 +1,201 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc A Resource is attributes representing the entity producing
%% telemetry. For example, by default the language (Erlang), name of this
%% library (`opentelemetry'), and version of this library are included in
%% the Resource.
%%
%% This module provides the functional interface for working with the
%% resource record.
%%
%% The `opentelemetry' library supports <i>resource detectors</i> to
%% detect attributes to include in the Resource. See {@link otel_resource_detector}
%% for the behaviour to detect resources, and the {@link otel_resource_app_env}
%% and {@link otel_resource_env_var} modules for built-in implementations.
%%
%% See the <a href="https://opentelemetry.io/docs/concepts/resources/">
%% OpenTelemetry Resource documentation</a> for more information on Resources.
%% @end
%%%-----------------------------------------------------------------------
-module(otel_resource).
-export([create/1,
create/2,
merge/2,
schema_url/1,
attributes/1,
is_key/2]).
-type key() :: unicode:latin1_binary() | atom().
%% values allowed in attributes of a resource are limited
-type value() :: unicode:latin1_binary() | integer() | float() | boolean().
%% A resource value.
-type schema_url() :: uri_string:uri_string().
%% A schema URL for the resource.
-define(MAX_LENGTH, 255).
-record(resource, {schema_url :: schema_url() | undefined,
attributes :: otel_attributes:t()}).
-type t() :: #resource{} | undefined.
%% The type that represents a resource.
-export_type([t/0]).
%% @equiv create(Attributes, undefined)
-spec create(#{key() => value()} | [{key(), value()}]) -> t().
create(Attributes) ->
create(Attributes, undefined).
%% @doc Creates a new resources from the given map or list of `Attributes' and
%% with the given `SchemaUrl'.
%%
%%
%% This function verifies each key and value, and drops any that don't pass verification.
-spec create(#{key() => value()} | [{key(), value()}], schema_url() | undefined) -> t().
create(Map, SchemaUrl) when is_map(Map) ->
create(maps:to_list(Map), SchemaUrl);
create(List, SchemaUrl) when is_list(List) ->
List1 = lists:filtermap(fun({K, V}) ->
%% TODO: log an info or debug message when dropping?
case try_check_key(K, true) of
{true, Key} ->
case check_value(V) of
{true, Value} ->
{true, {Key, Value}};
_ ->
false
end;
_ ->
false
end
end, lists:ukeysort(1, List)),
#resource{schema_url=SchemaUrl,
attributes=otel_attributes:new(List1, 128, 255)}.
%% @doc Returns the schema URL of the resource.
-spec schema_url(t()) -> schema_url() | undefined.
schema_url(#resource{schema_url=Schema}) ->
Schema;
schema_url(_) ->
undefined.
%% @doc Returns the attributes of the given `Resource'.
%%
%% This function returns `undefined' only in case `Resource' is an invalid argument
%% (not a resource record).
-spec attributes(t()) -> otel_attributes:t() | undefined.
attributes(#resource{attributes=Attributes}) ->
Attributes;
attributes(_) ->
undefined.
%% @doc Returns `true' if `Key' is valid and part of the given resource.
-spec is_key(key(), t()) -> boolean().
is_key(K, #resource{attributes=Attributes}) ->
case try_check_key(K, false) of
{true, Key} ->
maps:is_key(Key, otel_attributes:map(Attributes));
_ ->
false
end;
is_key(_, _) ->
false.
%% @doc Merges the two given resources.
%%
%% In case of collision, the first argument (`Resource') takes precedence.
-spec merge(t(), t()) -> t().
merge(#resource{schema_url=NewSchemaUrl,
attributes=NewAttributes}, CurrentResource=#resource{schema_url=CurrentSchemaUrl,
attributes=CurrentAttributes}) ->
SchameUrl = merge_schema_url(NewSchemaUrl, CurrentSchemaUrl),
NewMap = otel_attributes:map(NewAttributes),
CurrentResource#resource{schema_url=SchameUrl,
attributes=otel_attributes:set(NewMap, CurrentAttributes)}.
%%
%% when merging resources the schemas are checked to verify they match.
%% if they do match then the schema is set to `undefined' and the attributes are kept.
merge_schema_url(SchemaUrl, undefined) ->
SchemaUrl;
merge_schema_url(undefined, SchemaUrl) ->
SchemaUrl;
merge_schema_url(NewSchemaUrl, CurrentSchemaUrl) ->
merge_schema_url_(uri_string:normalize(NewSchemaUrl), uri_string:normalize(CurrentSchemaUrl)).
merge_schema_url_(SchemaUrl, SchemaUrl) ->
SchemaUrl;
merge_schema_url_(_, _) ->
undefined.
%% a resource key must be a non-empty latin1 string or atom, stored as atom
try_check_key(K, UnconditionalBinaryToAtom) ->
try check_key(K, UnconditionalBinaryToAtom)
catch error:badarg -> false
end.
check_key(<<>>, _) ->
false;
check_key(K, UnconditionalBinaryToAtom) when is_binary(K) ->
case check_string_value(K) of
{true, Key} when UnconditionalBinaryToAtom ->
{true, binary_to_atom(Key, latin1)};
{true, Key} ->
{true, binary_to_existing_atom(Key, latin1)};
false ->
false
end;
check_key(K, UnconditionalBinaryToAtom) when is_list(K) ->
check_key(list_to_binary(K), UnconditionalBinaryToAtom);
check_key(K, _) when is_atom(K) ->
% Atoms have an length upper limit of 255 utf8 codepoints, so the
% latin1 representation, if it exists, shares that limit
_ = atom_to_binary(K, latin1),
{true, K};
check_key(_, _) ->
false.
%% a resource value can be a latin1 string, integer, float or boolean
check_value(V) when is_integer(V) ;
is_float(V) ;
is_boolean(V) ->
{true, V};
check_value(V) when is_binary(V) ->
check_string_value(V);
check_value(V) when is_list(V) ->
try unicode:characters_to_binary(V) of
B ->
check_string_value(B)
catch
error:badarg ->
%% must be an array attribute value
{true, V}
end;
check_value(_) ->
false.
check_string_value(V) ->
%% all resource strings, key or value, must be latin1 with length less than 255
case string:length(V) =< ?MAX_LENGTH of
true ->
{true, V};
false ->
false
end.

View File

@ -0,0 +1,88 @@
%%%------------------------------------------------------------------------
%% Copyright 2020, OpenTelemetry Authors
%% 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.
%%
%% @doc Resource detector ({@link otel_resource_detector}) which adds attributes
%% to the `Resource' based on the value of `resource'
%% in the `opentelemetry' application's environment.
%%
%% For example, if the `opentelemetry' application environment has the following
%% configuration under the `resource' key:
%%
%% ```
%% [{service, #{name => "myservice",
%% namespace => "mynamespace"}}]
%% '''
%%
%% then it results in the `Resource' attributes `service.name' and `service.namespace'
%% set to `myservice' and `mynamespace"}}]' respectively.
%%
%% This detector is on by default (see the default configuration for `resource_detectors' in the
%% `opentelemetry' application environment).
%% @end
%%%-----------------------------------------------------------------------
-module(otel_resource_app_env).
-behaviour(otel_resource_detector).
-export([get_resource/1,
parse/1]).
%% @private
get_resource(_Config) ->
Attributes = parse(application:get_env(opentelemetry, resource, #{})),
otel_resource:create(Attributes).
%%
%% @private
parse(Attributes) when is_map(Attributes) ->
parse(maps:to_list(Attributes));
parse(Attributes) when is_list(Attributes) ->
lists:flatmap(fun({Key, Values}) when is_list(Key) ; is_binary(Key) ; is_atom(Key) ->
parse_values(to_string(Key), Values);
(_) ->
%% ignore anything else
[]
end, Attributes);
parse(_) ->
%% must be a map or list. ignore and return empty if it isn't
[].
parse_values(Key, Values) when is_map(Values) ->
parse_values(Key, maps:to_list(Values));
parse_values(Key, Values) when is_list(Values) ->
case io_lib:printable_unicode_list(Values) of
true ->
[{unicode:characters_to_binary(Key), unicode:characters_to_binary(Values)}];
false ->
lists:flatmap(fun({SubKey, Value=[{_,_}|_]}) ->
%% list of tuples means we have more subkeys
parse_values([Key, ".", to_string(SubKey)], Value);
({SubKey, Value}) when is_map(Value) ->
%% map value means we have more subkeys
parse_values([Key, ".", to_string(SubKey)], Value);
({SubKey, Value})->
[{otel_utils:assert_to_binary([Key, ".", to_string(SubKey)]), Value}]
end, Values)
end;
parse_values(Key, Value) ->
[{unicode:characters_to_binary(Key), Value}].
-spec to_string(atom() | binary() | list()) -> binary().
to_string(K) when is_atom(K) ->
atom_to_binary(K, utf8);
to_string(K) when is_list(K) ->
otel_utils:assert_to_binary(K);
to_string(K) when is_binary(K) ->
K.

View File

@ -0,0 +1,317 @@
%%%------------------------------------------------------------------------
%% Copyright 2020, OpenTelemetry Authors
%% 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.
%%
%% @doc Resource detectors are responsible for reading in attributes about
%% the runtime environment of a node (such as an environment variable or
%% some metadata endpoint provided by a cloud host) and returning a
%% {@link otel_resource:t()} made from those attributes.
%%
%% This module is meant for users who intend to write their own resource
%% detectors.
%%
%% This behaviour is a state machine (started by the `opentelemetry' application)
%% which spawns a process for each detector, collects the
%% results of running each, and merges them in the order they are defined. Once the
%% state machine process is ready, it will reply to {@link get_resource/1}
%% calls with the final {@link otel_resource:t()}.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_resource_detector).
-behaviour(gen_statem).
-export([start_link/1,
get_resource/0,
get_resource/1]).
-export([init/1,
callback_mode/0,
handle_event/4]).
-callback get_resource(term()) -> otel_resource:t().
%% Function that takes the configuration of a resource detector
%% and returns a resource.
-type detector() :: module() | {module(), term()}.
-include_lib("kernel/include/logger.hrl").
-record(data, {resource :: otel_resource:t(),
detectors :: [detector()],
detector_timeout :: integer()}).
%% @private
-spec start_link(Config) -> {ok, pid()} | ignore | {error, term()} when
Config :: #{resource_detectors := [module()],
resource_detector_timeout := integer()}.
start_link(Config) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Config], []).
%% @equiv get_resource(6000)
-spec get_resource() -> otel_resource:t().
get_resource() ->
get_resource(6000).
%% @doc Gets the resource formed by detecting attributes through resource
%% detectors.
%%
%% If the call doesn't complete within the given `Timeout' then an empty
%% resource is returned.
-spec get_resource(timeout()) -> otel_resource:t().
get_resource(Timeout) ->
try gen_statem:call(?MODULE, get_resource, Timeout)
catch
_:_ ->
%% TODO: should we return an error instead?
%% returning an empty resource ensures we continue on and
%% don't crash anything depending on the returned resource
%% but could mean we have an empty resource while the
%% gen_server later has a full resourced
otel_resource:create([])
end.
%% @private
init([#{resource_detectors := Detectors,
resource_detector_timeout := DetectorTimeout}]) ->
process_flag(trap_exit, true),
{ok, collecting, #data{resource=otel_resource:create([]),
detectors=Detectors,
detector_timeout=DetectorTimeout},
[{next_event, internal, spawn_detectors}]}.
%% @private
callback_mode() ->
[handle_event_function, state_enter].
%% @private
handle_event(enter, _, ready, Data=#data{resource=Resource}) ->
NewResource = default_resource_attributes(Resource),
{keep_state, Data#data{resource=NewResource}};
handle_event(enter, _, _, _) ->
keep_state_and_data;
handle_event(internal, spawn_detectors, collecting, Data=#data{detectors=Detectors}) ->
%% merging must be done in a specific order so Refs are kept in a list
ToCollectRefs = spawn_detectors(Detectors),
{next_state, next_state(ToCollectRefs), Data, [state_timeout(Data)]};
handle_event(info, {'EXIT', Pid, _}, {collecting, [{_, Pid, Detector} | Rest]}, Data) ->
?LOG_WARNING("detector ~p crashed while executing", [Detector]),
{next_state, next_state(Rest), Data, [state_timeout(Data)]};
handle_event(info, {resource, Ref, Resource}, {collecting, [{Ref, _, _} | Rest]},
Data=#data{resource=CurrentResource}) ->
NewResource = otel_resource:merge(Resource, CurrentResource),
{next_state, next_state(Rest), Data#data{resource=NewResource}, state_timeout(Data)};
handle_event(state_timeout, resource_detector_timeout, {collecting, [{_, Pid, Detector} | Rest]}, Data) ->
?LOG_WARNING("detector ~p timed out while executing", [Detector]),
%% may still have an EXIT in the mailbox but with `unlink' we might not
erlang:unlink(Pid),
erlang:exit(Pid, kill),
{next_state, next_state(Rest), Data, state_timeout(Data)};
handle_event(info, _, _, _Data) ->
%% merging resources must be done in order, so postpone the message
%% if it isn't the head of the list
{keep_state_and_data, [postpone]};
handle_event({call, From}, get_resource, ready, #data{resource=Resource}) ->
{keep_state_and_data, [{reply, From, Resource}]};
handle_event({call, _From}, get_resource, _, _Data) ->
%% can't get the resource until all detectors have completed
%% at which point this statem will be in the `ready' state
{keep_state_and_data, [postpone]};
handle_event(_, _, ready, _) ->
%% if in `ready' state get rid of all the postpones messages in
%% the mailbox that were postponed. Could be EXIT's or late resource
%% messages
keep_state_and_data.
%%
%% go to the `ready' state if the list of detectors to collect for is empty
next_state([]) ->
ready;
next_state(List) ->
{collecting, List}.
state_timeout(#data{detector_timeout=DetectorTimeout}) ->
{state_timeout, DetectorTimeout, resource_detector_timeout}.
spawn_detectors(Detectors) ->
lists:map(fun(Detector) ->
Ref = erlang:make_ref(),
Pid = spawn_detector(Detector, Ref),
{Ref, Pid, Detector}
end, Detectors).
spawn_detector(Detector={Module, Config}, Ref) ->
Self = self(),
erlang:spawn_link(fun() ->
try Module:get_resource(Config) of
Resource ->
Self ! {resource, Ref, Resource}
catch
C:T:S ->
?LOG_WARNING("caught exception while detector ~p was "
"executing: class=~p exception=~p stacktrace=~p",
[Detector, C, T, S]),
%% TODO: log about detector's exception
Self ! {resource, Ref, otel_resource:create([])}
end
end);
spawn_detector(Module, Ref) ->
spawn_detector({Module, []}, Ref).
default_resource_attributes(Resource) ->
ProgName = prog_name(),
ProcessResource = otel_resource:create([{'process.executable.name', ProgName} | process_attributes()]),
Resource1 = otel_resource:merge(ProcessResource, Resource),
Resource2 = add_service_name(Resource1, ProgName),
Resource3 = add_service_instance(Resource2),
add_telemetry_info(Resource3).
process_attributes() ->
OtpVsn = otp_vsn(),
ErtsVsn = erts_vsn(),
[{'process.runtime.name', unicode:characters_to_binary(emulator())},
{'process.runtime.version', unicode:characters_to_binary(ErtsVsn)},
{'process.runtime.description', unicode:characters_to_binary(runtime_description(OtpVsn, ErtsVsn))}].
runtime_description(OtpVsn, ErtsVsn) ->
io_lib:format("Erlang/OTP ~s erts-~s", [OtpVsn, ErtsVsn]).
erts_vsn() ->
erlang:system_info(version).
otp_vsn() ->
erlang:system_info(otp_release).
emulator() ->
erlang:system_info(machine).
prog_name() ->
%% RELEASE_PROG is set by mix and rebar3 release scripts
%% PROGNAME is an OS variable set by `erl' and rebar3 release scripts
unicode:characters_to_binary(os_or_default("RELEASE_PROG", os_or_default("PROGNAME", <<"erl">>))).
os_or_default(EnvVar, Default) ->
case os:getenv(EnvVar) of
false ->
Default;
Value ->
Value
end.
-dialyzer({nowarn_function, find_release/0}).
find_release() ->
try release_handler:which_releases(permanent) of
[{RelName, RelVsn, _Apps, permanent} | _] ->
{RelName, RelVsn}
catch
%% can happen if `release_handler' isn't available
%% or its process isn't started
_:_ ->
{release_name(), os:getenv("RELEASE_VSN")}
end.
release_name() ->
case os:getenv("RELEASE_NAME") of
false ->
%% older relx generated releases only set and export this variable
os:getenv("REL_NAME");
RelName ->
RelName
end.
%% if OTEL_SERVICE_NAME isn't set then check for service.name in attributes
%% if that isn't found then try finding the release name
%% if no release name we use the default service name
add_service_name(Resource, ProgName) ->
case os:getenv("OTEL_SERVICE_NAME") of
false ->
case otel_resource:is_key('service.name', Resource) of
false ->
ServiceResource = service_release_name(ProgName),
otel_resource:merge(ServiceResource, Resource);
true ->
Resource
end;
ServiceName ->
%% service.name resource first to override any other service.name
%% attribute that could be set in the resource
case unicode:characters_to_binary(ServiceName) of
{_, _, _} ->
?LOG_WARNING("error converting service name ~s to utf8. falling back on the release name for service.name resource attributes", [ServiceName]),
ServiceResource = service_release_name(ProgName),
otel_resource:merge(ServiceResource, Resource);
BinaryString ->
ServiceNameResource = otel_resource:create([{'service.name', BinaryString}]),
otel_resource:merge(ServiceNameResource, Resource)
end
end.
%% if OTEL_SERVICE_INSTANCE isn't set then check for service.name in attributes
%% if that isn't found then try getting node.
%% if node is nonode@nohost set a random instance id
add_service_instance(Resource) ->
case os:getenv("OTEL_SERVICE_INSTANCE") of
false ->
case otel_resource:is_key('service.instance.id', Resource) of
false ->
case erlang:node() of
nonode@nohost ->
ServiceInstanceId = otel_id_generator:generate_trace_id(),
ServiceInstanceResource = otel_resource:create([{'service.instance.id', ServiceInstanceId}]),
otel_resource:merge(ServiceInstanceResource, Resource);
ServiceInstance ->
ServiceInstance1 = erlang:atom_to_binary(ServiceInstance, utf8),
case binary:match(ServiceInstance1, <<"@localhost">>) of
nomatch ->
ServiceInstanceResource = otel_resource:create([{'service.instance.id', ServiceInstance1}]),
otel_resource:merge(ServiceInstanceResource, Resource);
_Match ->
ServiceInstanceId = otel_id_generator:generate_trace_id(),
ServiceInstanceResource = otel_resource:create([{'service.instance.id', ServiceInstanceId}]),
otel_resource:merge(ServiceInstanceResource, Resource)
end
end;
true ->
Resource
end;
ServiceInstance ->
ServiceInstanceResource = otel_resource:create([{'service.instance.id',
otel_utils:assert_to_binary(ServiceInstance)}]),
otel_resource:merge(ServiceInstanceResource, Resource)
end.
service_release_name(ProgName) ->
case find_release() of
{RelName, RelVsn} when RelName =/= false ->
otel_resource:create([{'service.name', RelName} |
case RelVsn of
false -> [];
_ -> [{'service.version', RelVsn}]
end]);
_ ->
otel_resource:create([{'service.name', <<"unknown_service:", ProgName/binary>>}])
end.
add_telemetry_info(Resource) ->
{ok, LibraryVsn} = application:get_key(opentelemetry, vsn),
LibraryName = <<"opentelemetry">>,
LibraryLanguage = <<"erlang">>,
ResourceAttributes = [{'telemetry.sdk.name', LibraryName},
{'telemetry.sdk.language', LibraryLanguage},
{'telemetry.sdk.version', LibraryVsn}],
TelemetryInfoResource = otel_resource:create(ResourceAttributes),
otel_resource:merge(TelemetryInfoResource, Resource).

View File

@ -12,24 +12,35 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% @doc
%% @doc Resource detector ({@link otel_resource_detector}) which adds attributes
%% to the `Resource' based on environment variables.
%%
%% This resource detector reads the `OTEL_RESOURCE_ATTRIBUTES' environment
%% variable and parses it as a comma-separated list of key-value pairs. For
% example, `key1=val1,key2=val2'.
%%
%% This detector is on by default (see the default configuration for `resource_detectors' in the
%% `opentelemetry' application environment).
%% @end
%%%-----------------------------------------------------------------------
-module(ot_resource_env_var).
-module(otel_resource_env_var).
-export([get_resource/0,
-behaviour(otel_resource_detector).
-export([get_resource/1,
parse/1]).
-define(OS_ENV, "OTEL_RESOURCE_LABELS").
-define(OS_ENV, "OTEL_RESOURCE_ATTRIBUTES").
-define(LABEL_LIST_SPLITTER, ",").
-define(LABEL_KEY_VALUE_SPLITTER, "=").
get_resource() ->
ot_resource:create(parse(os:getenv(?OS_ENV))).
%% @private
get_resource(_Config) ->
otel_resource:create(parse(os:getenv(?OS_ENV))).
%%
%% @private
-spec parse(false | string()) -> list().
parse(false) ->
[];

View File

@ -0,0 +1,140 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc Behaviour for defining samplers.
%%
%% A sampler should provide a function run on each started span that returns whether to
%% record and propagate, only record, or not record the span.
%%
%% For more information on the concept of <i>Sampling</i>, see
%% <a href="https://opentelemetry.io/docs/concepts/sampling/">Sampling in the OpenTelemetry
%% documentation</a> or the
%% <a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#sampling">Sampling spec</a>.
%% For examples of configuring samplers or implementing your own sampler,
%% see <a href="https://opentelemetry.io/docs/languages/erlang/sampling/">the OpenTelemetry
%% Erlang documentation</a>.
%%
%% <h3>Configuration</h3>
%%
%% To configure sampling for the `opentelemetry' application, see
%% <a href="https://hexdocs.pm/opentelemetry/readme.html#samplers">the documentation</a>.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_sampler).
-export([description/1, new/1, should_sample/7]).
-export_type([description/0,
sampler_spec/0,
sampler_config/0,
sampler_opts/0,
sampling_decision/0,
sampling_result/0,
t/0]).
-callback setup(sampler_opts()) -> sampler_config().
%% Called when a sampler is created to set up the sampler.
%% Should return the sampler configuration that is then passed to other callbacks.
-callback description(sampler_config()) -> description().
%% Should return the description of the sampler.
-callback should_sample(
otel_ctx:t(),
opentelemetry:trace_id(),
otel_links:t(),
opentelemetry:span_name(),
opentelemetry:span_kind(),
opentelemetry:attributes_map(),
sampler_config()
) -> sampling_result().
%% Main callback that determines whether a span should be sampled.\
-include("otel_sampler.hrl").
-type description() :: unicode:unicode_binary().
%% The description of the sampler.
-type sampler_config() :: term().
%% Any term used to configured a given sampler.
-type sampler_opts() :: term().
%% Any options passed to a sampler.
-type builtin_sampler() ::
always_on
| always_off
| {trace_id_ratio_based, float()}
| {parent_based, #{
remote_parent_sampled => sampler_spec(),
remote_parent_not_sampled => sampler_spec(),
local_parent_sampled => sampler_spec(),
local_parent_not_sampled => sampler_spec(),
root => sampler_spec()
}}.
%% A built-in sampler.
-type sampler_spec() :: builtin_sampler() | {module(), sampler_opts()}.
%% Specification to create a sampler.
-type sampling_decision() :: ?DROP | ?RECORD_ONLY | ?RECORD_AND_SAMPLE.
%% The decision that a sampler can make on a given span.
-type sampling_result() :: {
sampling_decision(),
opentelemetry:attributes_map(),
opentelemetry:tracestate() | otel_tracestate:members()
}.
%% The result of a sampling decision.
-opaque t() :: {module(), description(), sampler_opts()}.
%% A sampler.
%% @doc Returns a sampler based on the given specification.
-spec new(SamplerSpec :: sampler_spec()) -> t().
new(always_on) ->
new({otel_sampler_always_on, #{}});
new(always_off) ->
new({otel_sampler_always_off, #{}});
new({trace_id_ratio_based, Opts}) ->
new({otel_sampler_trace_id_ratio_based, Opts});
new({parent_based, Opts}) ->
new({otel_sampler_parent_based, Opts});
new({Sampler, Opts}) ->
Config = Sampler:setup(Opts),
{Sampler, Sampler:description(Config), Config}.
%% @private
-spec should_sample(
t(),
otel_ctx:t(),
opentelemetry:trace_id(),
otel_links:t(),
opentelemetry:span_name(),
opentelemetry:span_kind(),
opentelemetry:attributes_map()
) -> sampling_result().
should_sample({Sampler, _, Config}, Ctx, TraceId, Links, SpanName, Kind, Attributes) ->
case Sampler:should_sample(Ctx, TraceId, Links, SpanName, Kind, Attributes, Config) of
%% to support backwards compatibility with when `tracestate' was just a list, not
%% a record, we accept a list and create a new `tracestate'
{Decision, Attributes, Tracestate} when is_list(Tracestate) ->
{Decision, Attributes, otel_tracestate:new(Tracestate)};
Result ->
Result
end.
%% @doc Returns the description of the given sampler.
-spec description(t()) -> description().
description(_Sampler = {_, Description, _}) -> Description.

View File

@ -12,38 +12,29 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% @doc
%% @doc An {@link otel_sampler} that drops all spans.
%%
%% This is one of the
%% <a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#built-in-samplers">built-in
%% samplers</a> provided by the OpenTelemetry SDK.
%% @end
%%%-------------------------------------------------------------------------
-module(ot_metric_exporter).
-module(otel_sampler_always_off).
-behaviour(gen_server).
-behavior(otel_sampler).
-export([start_link/1,
export/1]).
-export([init/1,
handle_call/3,
handle_cast/2]).
-export([description/1, setup/1, should_sample/7]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_sampler.hrl").
-record(state, {exporter :: {module(), term()}}).
%% @private
setup(_Opts) -> [].
start_link(Opts) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []).
%% @private
description(_) -> <<"AlwaysOffSampler">>.
export(Records) ->
{Module, Args} = gen_server:call(?MODULE, exporter),
erlang:apply(Module, export, [Records | Args]).
init(Opts) ->
Exporter = proplists:get_value(metric_exporter, Opts, {ot_metric_exporter_stdout, []}),
{ok, #state{exporter=Exporter}}.
handle_call(exporter, _From, State=#state{exporter=Exporter}) ->
{reply, Exporter, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
%% @private
should_sample(Ctx, _TraceId, _Links, _SpanName, _SpanKind, _Attributes, _Opts) ->
SpanCtx = otel_tracer:current_span_ctx(Ctx),
{?DROP, [], otel_span:tracestate(SpanCtx)}.

View File

@ -0,0 +1,40 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc An {@link otel_sampler} that records and samples all spans.
%%
%% This is one of the
%% <a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#built-in-samplers">built-in
%% samplers</a> provided by the OpenTelemetry SDK.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_sampler_always_on).
-behavior(otel_sampler).
-export([description/1, setup/1, should_sample/7]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_sampler.hrl").
%% @private
setup(_Opts) -> [].
%% @private
description(_) -> <<"AlwaysOnSampler">>.
%% @private
should_sample(Ctx, _TraceId, _Links, _SpanName, _SpanKind, _Attributes, _Opts) ->
SpanCtx = otel_tracer:current_span_ctx(Ctx),
{?RECORD_AND_SAMPLE, [], otel_span:tracestate(SpanCtx)}.

View File

@ -0,0 +1,115 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc An {@link otel_sampler} that makes the decision based on the parent.
%%
%% This sampler decides with the following possibilities:
%% <ol>
%% <li>a remote parent that is sampled (by default `always_on');</li>
%% <li>a remote parent that is not sampled (by default `always_off');</li>
%% <li>a local parent that is sampled (by default `always_on');</li>
%% <li>a local parent that is not sampled (by default `always_off');</li>
%% <li>no parent (by default `always_on').</li>
%% </ol>
%%
%% For each of these cases a different sampler can be configured.
%% For options, see {@link opts()}.
%%
%% This is one of the
%% <a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#built-in-samplers">built-in
%% samplers</a> provided by the OpenTelemetry SDK.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_sampler_parent_based).
-behavior(otel_sampler).
-export([description/1, setup/1, should_sample/7]).
-export_type([opts/0]).
-include_lib("kernel/include/logger.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-type opts() :: #{
remote_parent_sampled => otel_sampler:sampler_spec(),
remote_parent_not_sampled => otel_sampler:sampler_spec(),
local_parent_sampled => otel_sampler:sampler_spec(),
local_parent_not_sampled => otel_sampler:sampler_spec(),
root => otel_sampler:sampler_spec()
}.
%% Options to configure this sampler.
%% @private
setup(Opts = #{root := RootSpec}) ->
RemoteParentSampledSampler = sampler_for_spec(remote_parent_sampled, Opts, always_on),
RemoteParentNotSampledSampler = sampler_for_spec(remote_parent_not_sampled, Opts, always_off),
LocalParentSampledSampler = sampler_for_spec(local_parent_sampled, Opts, always_on),
LocalParentNotSampledSampler = sampler_for_spec(local_parent_not_sampled, Opts, always_off),
RootSampler = otel_sampler:new(RootSpec),
#{
root => RootSampler,
remote_parent_sampled => RemoteParentSampledSampler,
remote_parent_not_sampled => RemoteParentNotSampledSampler,
local_parent_sampled => LocalParentSampledSampler,
local_parent_not_sampled => LocalParentNotSampledSampler
};
setup(Opts) ->
?LOG_INFO("No sampler spec found for parent_based 'root' option. The 'always_on' sampler will be used for root spans."),
setup(Opts#{root => always_on}).
sampler_for_spec(Key, Opts, DefaultModule) ->
Spec = maps:get(Key, Opts, DefaultModule),
otel_sampler:new(Spec).
%% @private
description(#{
root := RootSampler,
remote_parent_sampled := RemoteParentSampler,
remote_parent_not_sampled := RemoteParentNotSampler,
local_parent_sampled := LocalParentSampler,
local_parent_not_sampled := LocalParentNotSampler
}) ->
<<"ParentBased{root:", (otel_sampler:description(RootSampler))/binary, ",remoteParentSampled:",
(otel_sampler:description(RemoteParentSampler))/binary, ",remoteParentNotSampled:",
(otel_sampler:description(RemoteParentNotSampler))/binary, ",localParentSampled:",
(otel_sampler:description(LocalParentSampler))/binary, ",localParentNotSampled:",
(otel_sampler:description(LocalParentNotSampler))/binary, "}">>.
%% @private
should_sample(Ctx, TraceId, Links, SpanName, SpanKind, Attributes, Config) ->
ParentSpanCtx = otel_tracer:current_span_ctx(Ctx),
SamplerKey = parent_based_sampler(ParentSpanCtx),
{Sampler, _Description, SamplerOpts} = maps:get(SamplerKey, Config),
Sampler:should_sample(Ctx, TraceId, Links, SpanName, SpanKind, Attributes, SamplerOpts).
%% remote parent sampled
parent_based_sampler(#span_ctx{trace_flags = TraceFlags, is_remote = true}) when
?IS_SAMPLED(TraceFlags)
->
remote_parent_sampled;
%% remote parent not sampled
parent_based_sampler(#span_ctx{is_remote = true}) ->
remote_parent_not_sampled;
%% local parent sampled
parent_based_sampler(#span_ctx{trace_flags = TraceFlags}) when
?IS_SAMPLED(TraceFlags)
->
local_parent_sampled;
%% local parent not sampled
parent_based_sampler(#span_ctx{}) ->
local_parent_not_sampled;
%% root
parent_based_sampler(_SpanCtx) ->
root.

View File

@ -0,0 +1,80 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc An {@link otel_sampler} that samples a configured percentage of spans.
%%
%% This sampler samples a configured percentage of spans, where the sampling
%% decision is <i>deterministic</i> with respect to the span trace ID. That means
%% the sampler always makes the same decision for the same trace ID.
%%
%% This is one of the
%% <a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#built-in-samplers">built-in
%% samplers</a> provided by the OpenTelemetry SDK.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_sampler_trace_id_ratio_based).
-behavior(otel_sampler).
-export([description/1, setup/1, should_sample/7]).
-export_type([config/0, probability/0]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_sampler.hrl").
-type probability() :: float().
%% A probability on whether to sample a span, between `0.0' and `1.0'.
-type config() :: #{probability := probability(), id_upper_bound := integer()}.
%% The configuration for this sampler.
%% 2^63 - 1
-define(MAX_VALUE, 9223372036854775807).
%% @private
-spec setup(probability()) -> config().
setup(Probability) ->
IdUpperBound =
case Probability of
P when P == 0.0 ->
0;
P when P =:= 1.0 ->
?MAX_VALUE;
P when P >= 0.0 andalso P =< 1.0 ->
P * ?MAX_VALUE
end,
#{probability => Probability, id_upper_bound => IdUpperBound}.
%% @private
description(#{probability := Probability}) ->
unicode:characters_to_binary(io_lib:format("TraceIdRatioBased{~.6f}", [Probability])).
%% @private
should_sample(Ctx, TraceId, _Links, _SpanName, _SpanKind, _Attributes, #{
id_upper_bound := IdUpperBound
}) ->
SpanCtx = otel_tracer:current_span_ctx(Ctx),
{decide(TraceId, IdUpperBound), [], otel_span:tracestate(SpanCtx)}.
decide(undefined, _IdUpperBound) ->
?DROP;
decide(0, _IdUpperBound) ->
?DROP;
decide(TraceId, IdUpperBound) ->
Lower64Bits = TraceId band ?MAX_VALUE,
case erlang:abs(Lower64Bits) < IdUpperBound of
true -> ?RECORD_AND_SAMPLE;
false -> ?DROP
end.

View File

@ -0,0 +1,269 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc This Span Processor synchronously exports each ended Span.
%%
%% Use this processor if ending a Span should block until it has been
%% exported. This is useful for cases like a serverless environment where
%% the application will possibly be suspended after handling a request.
%%
%% @end
%%%-----------------------------------------------------------------------
-module(otel_simple_processor).
-behaviour(gen_statem).
-behaviour(otel_span_processor).
-export([start_link/1,
on_start/3,
on_end/2,
force_flush/1,
report_cb/1,
%% deprecated
set_exporter/1,
set_exporter/2,
set_exporter/3]).
-export([init/1,
callback_mode/0,
idle/3,
exporting/3,
terminate/3]).
%% uncomment when OTP-23 becomes the minimum required version
%% -deprecated({set_exporter, 1, "set through the otel_tracer_provider instead"}).
%% -deprecated({set_exporter, 2, "set through the otel_tracer_provider instead"}).
%% -deprecated({set_exporter, 3, "set through the otel_tracer_provider instead"}).
-eqwalizer({nowarn_function, on_end/2}).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include_lib("kernel/include/logger.hrl").
-include("otel_span.hrl").
-record(data, {exporter :: {module(), term()} | undefined,
exporter_config :: {module(), term()} | undefined | none,
current_from :: gen_statem:from() | undefined,
resource :: otel_resource:t(),
handed_off_table :: atom() | undefined,
runner_pid :: pid() | undefined,
exporting_timeout_ms :: integer()}).
-define(DEFAULT_EXPORTER_TIMEOUT_MS, timer:minutes(5)).
-define(NAME_TO_ATOM(Name, Unique), list_to_atom(lists:concat([Name, "_", Unique]))).
%% require a unique name to distinguish multiple simple processors while
%% still having a single name, instead of a possibly changing pid, to
%% communicate with the processor
%% @doc Starts a Simple Span Processor.
%% @end
-spec start_link(#{name := atom() | list()}) -> {ok, pid(), map()}.
start_link(Config=#{name := Name}) ->
RegisterName = ?NAME_TO_ATOM(?MODULE, Name),
Config1 = Config#{reg_name => RegisterName},
{ok, Pid} = gen_statem:start_link({local, RegisterName}, ?MODULE, [Config1], []),
{ok, Pid, Config1}.
%% @deprecated Please use {@link otel_tracer_provider}
set_exporter(Exporter) ->
set_exporter(global, Exporter, []).
%% @deprecated Please use {@link otel_tracer_provider}
-spec set_exporter(module(), term()) -> ok.
set_exporter(Exporter, Options) ->
gen_statem:call(?REG_NAME(global), {set_exporter, {Exporter, Options}}).
%% @deprecated Please use {@link otel_tracer_provider}
-spec set_exporter(atom(), module(), term()) -> ok.
set_exporter(Name, Exporter, Options) ->
gen_statem:call(?REG_NAME(Name), {set_exporter, {Exporter, Options}}).
%% @private
-spec on_start(otel_ctx:t(), opentelemetry:span(), otel_span_processor:processor_config())
-> opentelemetry:span().
on_start(_Ctx, Span, _) ->
Span.
%% @private
-spec on_end(opentelemetry:span(), otel_span_processor:processor_config())
-> true | dropped | {error, invalid_span} | {error, no_export_buffer}.
on_end(#span{trace_flags=TraceFlags}, _) when not(?IS_SAMPLED(TraceFlags)) ->
dropped;
on_end(Span=#span{}, #{reg_name := RegName}) ->
gen_statem:call(RegName, {export, Span});
on_end(_Span, _) ->
{error, invalid_span}.
%% @private
-spec force_flush(#{reg_name := gen_statem:server_ref()}) -> ok.
force_flush(#{reg_name := RegName}) ->
gen_statem:cast(RegName, force_flush).
%% @private
init([Args]) ->
process_flag(trap_exit, true),
ExportingTimeout = maps:get(exporting_timeout_ms, Args, ?DEFAULT_EXPORTER_TIMEOUT_MS),
%% TODO: this should be passed in from the tracer server
Resource = case maps:find(resource, Args) of
{ok, R} ->
R;
error ->
otel_resource_detector:get_resource()
end,
%% Resource = otel_tracer_provider:resource(),
{ok, idle, #data{exporter=undefined,
exporter_config=maps:get(exporter, Args, none),
resource = Resource,
handed_off_table=undefined,
exporting_timeout_ms=ExportingTimeout},
[{next_event, internal, init_exporter}]}.
%% @private
callback_mode() ->
state_functions.
%% @private
idle({call, From}, {export, _Span}, #data{exporter=undefined}) ->
{keep_state_and_data, [{reply, From, dropped}]};
idle({call, From}, {export, Span}, Data) ->
{next_state, exporting, Data, [{next_event, internal, {export, From, Span}}]};
idle(EventType, Event, Data) ->
handle_event_(idle, EventType, Event, Data).
%% @private
exporting({call, _From}, {export, _}, _) ->
{keep_state_and_data, [postpone]};
exporting(internal, {export, From, Span}, Data=#data{exporting_timeout_ms=ExportingTimeout}) ->
{OldTableName, RunnerPid} = export_span(Span, Data),
{keep_state, Data#data{runner_pid=RunnerPid,
current_from=From,
handed_off_table=OldTableName},
[{state_timeout, ExportingTimeout, exporting_timeout}]};
exporting(state_timeout, exporting_timeout, Data=#data{current_from=From,
handed_off_table=_ExportingTable}) ->
%% kill current exporting process because it is taking too long
%% which deletes the exporting table, so create a new one and
%% repeat the state to force another span exporting immediately
Data1 = kill_runner(Data),
{next_state, idle, Data1, [{reply, From, {error, timeout}}]};
%% important to verify runner_pid and FromPid are the same in case it was sent
%% after kill_runner was called but before it had done the unlink
exporting(info, {'EXIT', FromPid, _}, Data=#data{runner_pid=FromPid}) ->
complete_exporting(Data);
%% important to verify runner_pid and FromPid are the same in case it was sent
%% after kill_runner was called but before it had done the unlink
exporting(info, {completed, FromPid}, Data=#data{runner_pid=FromPid}) ->
complete_exporting(Data);
exporting(EventType, Event, Data) ->
handle_event_(exporting, EventType, Event, Data).
handle_event_(_, internal, init_exporter, Data=#data{exporter=undefined,
exporter_config=ExporterConfig}) ->
Exporter = otel_exporter:init(ExporterConfig),
{keep_state, Data#data{exporter=Exporter}};
handle_event_(_, {call, From}, {set_exporter, Exporter}, Data=#data{exporter=OldExporter}) ->
otel_exporter:shutdown(OldExporter),
{keep_state, Data#data{exporter=otel_exporter:init(Exporter)}, [{reply, From, ok}]};
handle_event_(_, _, _, _) ->
keep_state_and_data.
%% @private
terminate(_, _, _Data) ->
ok.
%%
complete_exporting(Data=#data{current_from=From,
handed_off_table=ExportingTable})
when ExportingTable =/= undefined ->
{next_state, idle, Data#data{current_from=undefined,
runner_pid=undefined,
handed_off_table=undefined},
[{reply, From, ok}]}.
kill_runner(Data=#data{runner_pid=RunnerPid}) when RunnerPid =/= undefined ->
Mon = erlang:monitor(process, RunnerPid),
erlang:unlink(RunnerPid),
erlang:exit(RunnerPid, kill),
%% Wait for the runner process termination to be sure that
%% the export table is destroyed and can be safely recreated
receive
{'DOWN', Mon, process, RunnerPid, _} ->
Data#data{runner_pid=undefined, handed_off_table=undefined}
end.
new_export_table(Name) ->
ets:new(Name, [public,
{write_concurrency, true},
duplicate_bag,
%% OpenTelemetry exporter protos group by the
%% instrumentation_scope. So using instrumentation_scope
%% as the key means we can easily lookup all spans for
%% for each instrumentation_scope and export together.
{keypos, #span.instrumentation_scope}]).
export_span(Span, #data{exporter=Exporter,
resource=Resource}) ->
Table = new_export_table(otel_simple_processor_table),
_ = ets:insert(Table, Span),
Self = self(),
RunnerPid = erlang:spawn_link(fun() -> send_spans(Self, Resource, Exporter) end),
ets:give_away(Table, RunnerPid, export),
{Table, RunnerPid}.
%% Additional benefit of using a separate process is calls to `register` won't
%% timeout if the actual exporting takes longer than the call timeout
send_spans(FromPid, Resource, Exporter) ->
receive
{'ETS-TRANSFER', Table, FromPid, export} ->
export(Exporter, Resource, Table),
ets:delete(Table),
completed(FromPid)
end.
completed(FromPid) ->
FromPid ! {completed, self()}.
export(undefined, _, _) ->
true;
export(Exporter, Resource, SpansTid) ->
%% don't let a exporter exception crash us
%% and return true if exporter failed
try
otel_exporter_traces:export(Exporter, SpansTid, Resource) =:= failed_not_retryable
catch
Kind:Reason:StackTrace ->
?LOG_INFO(#{source => exporter,
during => export,
kind => Kind,
reason => Reason,
exporter => Exporter,
stacktrace => StackTrace}, #{report_cb => fun ?MODULE:report_cb/1}),
true
end.
%% logger format functions
%% @private
report_cb(#{source := exporter,
during := export,
kind := Kind,
reason := Reason,
exporter := {ExporterModule, _},
stacktrace := StackTrace}) ->
{"exporter threw exception: exporter=~p ~ts",
[ExporterModule, otel_utils:format_exception(Kind, Reason, StackTrace)]}.

View File

@ -0,0 +1,209 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc
%% ETS backed interface for working with spans.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_span_ets).
-behaviour(gen_server).
-export([start_link/1,
init/1,
handle_call/3,
handle_cast/2]).
-export([start_span/7,
end_span/1,
end_span/2,
get_ctx/1,
set_attribute/3,
set_attributes/2,
add_event/3,
add_events/2,
set_status/2,
update_name/2]).
%% since `span_ctx' and `span' are in the API the `span_sdk' has to be term()
-eqwalizer({nowarn_function, get_ctx/1}).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_span.hrl").
-include("otel_span_ets.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-include_lib("opentelemetry_api/include/gradualizer.hrl").
-record(state, {}).
start_link(Opts) ->
gen_server:start_link(?MODULE, Opts, []).
%% @doc Start a span and insert into the active span ets table.
-spec start_span(otel_ctx:t(), opentelemetry:span_name(), otel_sampler:t(), otel_id_generator:t(),
otel_span:start_config(), fun(), otel_tracer_server:instrumentation_scope() | undefined)
-> opentelemetry:span_ctx().
start_span(Ctx, Name, Sampler, IdGeneratorModule, Opts, Processors, InstrumentationScope) ->
case otel_span_utils:start_span(Ctx, Name, Sampler, IdGeneratorModule, Opts) of
{SpanCtx=#span_ctx{is_recording=true}, Span=#span{}} ->
Span1 = Span#span{instrumentation_scope=InstrumentationScope},
Span2 = Processors(Ctx, Span1),
case storage_insert(Span2) of
true ->
SpanCtx;
_ ->
%% adding the span to storage failed, this means there
%% is no span backing the spanctx and we must return
%% a noop span instead
otel_tracer_noop:noop_span_ctx()
end;
{SpanCtx, #span{}} ->
%% span isn't recorded so don't run processors or insert into ets table
SpanCtx
end.
end_span(SpanCtx=#span_ctx{span_sdk={_, OnEndProcessors}}) ->
end_span(SpanCtx, undefined, OnEndProcessors).
end_span(SpanCtx=#span_ctx{span_sdk={_, OnEndProcessors}}, Timestamp) ->
end_span(SpanCtx, Timestamp, OnEndProcessors).
%% @doc End a span based on its context and send to exporter.
-spec end_span(opentelemetry:span_ctx(), integer() | undefined, fun()) -> boolean() | {error, term()}.
end_span(#span_ctx{span_id=SpanId,
is_recording=true,
tracestate=Tracestate}, Timestamp, Processors) ->
case ets:take(?SPAN_TAB, SpanId) of
[Span] ->
Span1 = otel_span_utils:end_span((?assert_type(Span, #span{}))#span{tracestate=Tracestate,
is_recording=false}, Timestamp),
Processors(Span1);
_ ->
false
end;
end_span(_, _, _) ->
true.
-spec get_ctx(opentelemetry:span()) -> opentelemetry:span_ctx().
get_ctx(#span{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
is_recording=IsRecording}) ->
#span_ctx{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
is_recording=IsRecording}.
-spec set_attribute(opentelemetry:span_ctx() | undefined,
opentelemetry:attribute_key(),
opentelemetry:attribute_value()) -> boolean().
set_attribute(#span_ctx{span_id=SpanId}, Key, Value) ->
try ets:lookup_element(?SPAN_TAB, SpanId, #span.attributes) of
Attributes ->
ets:update_element(?SPAN_TAB, SpanId, {#span.attributes, otel_attributes:set(Key, Value, Attributes)})
catch error:badarg ->
false
end;
set_attribute(_, _, _) ->
false.
%% Note: Spans are referenced through the current active span context in a process
%% and thus modified only by a single process, so concurrent updates of the same field
%% are not a real concern. This allows `add_events' and `set_attributes' to lookup and
%% update only the specific element of the `span' without worrying about it having been
%% changed by another process between the lookup and update.
-spec set_attributes(opentelemetry:span_ctx() | undefined, opentelemetry:attributes_map()) -> boolean().
set_attributes(#span_ctx{span_id=SpanId}, NewAttributes) ->
try ets:lookup_element(?SPAN_TAB, SpanId, #span.attributes) of
Attributes ->
ets:update_element(?SPAN_TAB, SpanId, {#span.attributes,
otel_attributes:set(NewAttributes, Attributes)})
catch error:badarg ->
false
end.
-spec add_event(opentelemetry:span_ctx() | undefined, unicode:unicode_binary(), opentelemetry:attributes_map()) -> boolean().
add_event(SpanCtx, Name, Attributes) ->
Events = opentelemetry:events([{Name, Attributes}]),
add_events(SpanCtx, Events).
-spec add_events(opentelemetry:span_ctx() | undefined, [opentelemetry:event()]) -> boolean().
add_events(#span_ctx{span_id=SpanId}, NewEvents) ->
try ets:lookup_element(?SPAN_TAB, SpanId, #span.events) of
Events ->
ets:update_element(?SPAN_TAB, SpanId, {#span.events, otel_events:add(NewEvents, Events)})
catch error:badarg ->
false
end.
-spec set_status(opentelemetry:span_ctx() | undefined, opentelemetry:status()) -> boolean().
set_status(#span_ctx{span_id=SpanId}, Status=#status{code=NewCode}) ->
try ets:lookup_element(?SPAN_TAB, SpanId, #span.status) of
#status{code=?OTEL_STATUS_ERROR} when NewCode =:= ?OTEL_STATUS_OK ->
%% can only set status to OK if it has been set to ERROR before
ets:update_element(?SPAN_TAB, SpanId, {#span.status, Status});
#status{code=?OTEL_STATUS_UNSET} ->
%% if UNSET then the status can be updated to OK or ERROR
ets:update_element(?SPAN_TAB, SpanId, {#span.status, Status});
undefined ->
%% if undefined then the status can be updated to anything
ets:update_element(?SPAN_TAB, SpanId, {#span.status, Status});
_ ->
%% nothing to do since status code is either
%% OK or ERROR but NewCode is not OK
false
catch error:badarg ->
false
end;
set_status(_, _) ->
false.
-spec update_name(opentelemetry:span_ctx() | undefined, opentelemetry:span_name()) -> boolean().
update_name(#span_ctx{span_id=SpanId}, Name) ->
ets:update_element(?SPAN_TAB, SpanId, {#span.name, Name});
update_name(_, _) ->
false.
%%
storage_insert(undefined) ->
true;
storage_insert(Span) ->
try
ets:insert(?SPAN_TAB, Span)
catch
error:badarg ->
false
end.
init(_Opts) ->
%% ets table is required for other parts to not crash so we create
%% it in init and not in a handle_continue or whatever else
case ets:info(?SPAN_TAB, name) of
undefined ->
ets:new(?SPAN_TAB, [named_table, public,
{write_concurrency, true},
{keypos, #span.span_id}]);
_ ->
ok
end,
{ok, #state{}}.
handle_call(_Msg, _From, State) ->
{noreply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.

View File

@ -1 +1,2 @@
-define(SPAN_TAB, otel_span_table).

View File

@ -0,0 +1,82 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc Module for setting the global limits for the number of attributes,
%% events and links on a Span.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_span_limits).
-export([get/0,
set/1,
attribute_count_limit/0,
attribute_value_length_limit/0,
event_count_limit/0,
link_count_limit/0,
attribute_per_event_limit/0,
attribute_per_link_limit/0]).
-include("otel_span.hrl").
-define(SPAN_LIMITS_KEY, {?MODULE, span_limits}).
-spec get() -> #span_limits{}.
get() ->
persistent_term:get(?SPAN_LIMITS_KEY).
-spec set(otel_configuration:t()) -> ok.
set(#{attribute_count_limit := AttributeCountLimit,
attribute_value_length_limit := AttributeValueLengthLimit,
event_count_limit := EventCountLimit,
link_count_limit := LinkCountLimit,
attribute_per_event_limit := AttributePerEventLimit,
attribute_per_link_limit := AttributePerLinkLimit}) ->
SpanLimits = #span_limits{attribute_count_limit=AttributeCountLimit,
attribute_value_length_limit=AttributeValueLengthLimit,
event_count_limit=EventCountLimit,
link_count_limit=LinkCountLimit,
attribute_per_event_limit=AttributePerEventLimit,
attribute_per_link_limit=AttributePerLinkLimit},
persistent_term:put(?SPAN_LIMITS_KEY, SpanLimits).
attribute_count_limit() ->
get_limit(attribute_count_limit, ?MODULE:get()).
attribute_value_length_limit() ->
get_limit(attribute_value_length_limit, ?MODULE:get()).
event_count_limit() ->
get_limit(event_count_limit, ?MODULE:get()).
link_count_limit() ->
get_limit(link_count_limit, ?MODULE:get()).
attribute_per_event_limit() ->
get_limit(attribute_per_event_limit, ?MODULE:get()).
attribute_per_link_limit() ->
get_limit(attribute_per_link_limit, ?MODULE:get()).
get_limit(attribute_count_limit, #span_limits{attribute_count_limit=AttributeCountLimit}) ->
AttributeCountLimit;
get_limit(attribute_value_length_limit, #span_limits{attribute_value_length_limit=AttributeValueLengthLimit}) ->
AttributeValueLengthLimit;
get_limit(event_count_limit, #span_limits{event_count_limit=EventCountLimit}) ->
EventCountLimit;
get_limit(link_count_limit, #span_limits{link_count_limit=LinkCountLimit}) ->
LinkCountLimit;
get_limit(attribute_per_event_limit, #span_limits{attribute_per_event_limit=AttributePerEventLimit}) ->
AttributePerEventLimit;
get_limit(attribute_per_link_limit, #span_limits{attribute_per_link_limit=AttributePerLinkLimit}) ->
AttributePerLinkLimit.

View File

@ -0,0 +1,55 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc Behaviour each Span Processor must implement.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_span_processor).
-export([start_link/2]).
-type processor_config() :: term().
-export_type([processor_config/0]).
-callback processor_init(pid(), processor_config()) -> processor_config().
-callback on_start(otel_ctx:t(), opentelemetry:span(), processor_config()) -> opentelemetry:span().
-callback on_end(opentelemetry:span(), processor_config()) -> true |
dropped |
{error, invalid_span} |
{error, no_export_buffer}.
-callback force_flush(processor_config()) -> ok |
{error, term()}.
-optional_callbacks([processor_init/2]).
%% @doc Starts a span processor.
%%
%% `Module' must implement the `otel_span_processor' behaviour. This function
%% calls `Module:start_link/1' with `Config' as the argument.
%% @end
-spec start_link(module(), Config) -> {ok, pid(), Config} | {error, term()} when
Config :: processor_config().
start_link(Module, Config) ->
case Module:start_link(Config) of
{ok, Pid} ->
{ok, Pid, Config};
{ok, Pid, Config1} ->
{ok, Pid, Config1};
{error, _}=Error ->
Error
end.

View File

@ -0,0 +1,39 @@
%%%------------------------------------------------------------------------
%% Copyright 2022, OpenTelemetry Authors
%% 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.
%%
%% @private
%% @end
%%%-------------------------------------------------------------------------
-module(otel_span_processor_sup).
-behaviour(supervisor).
-export([start_link/1]).
-export([init/1]).
-define(SERVER, ?MODULE).
start_link(RegName) ->
supervisor:start_link({local, RegName}, ?MODULE, []).
init([]) ->
SupFlags = #{strategy => simple_one_for_one,
intensity => 1,
period => 5},
ChildSpecs = [#{id => otel_span_processor,
start => {otel_span_processor, start_link, []},
shutdown => 5000}],
{ok, {SupFlags, ChildSpecs}}.

View File

@ -12,10 +12,9 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% @doc
%% @end
%% @private
%%%-------------------------------------------------------------------------
-module(ot_span_sup).
-module(otel_span_sup).
-behaviour(supervisor).
@ -26,31 +25,31 @@
-define(SERVER, ?MODULE).
start_link(Opts) ->
supervisor:start_link({local, ?SERVER}, ?MODULE, [Opts]).
start_link(Config) ->
supervisor:start_link({local, ?SERVER}, ?MODULE, [Config]).
start_child(ChildSpec) ->
supervisor:start_child(?SERVER, ChildSpec).
init([Opts]) ->
init([Config]) ->
SupFlags = #{strategy => one_for_one,
intensity => 1,
period => 5},
SweeperOpts = proplists:get_value(sweeper, Opts, #{}),
Sweeper = #{id => ot_span_sweeper,
start => {ot_span_sweeper, start_link, [SweeperOpts]},
SweeperConfig = maps:get(sweeper, Config),
Sweeper = #{id => otel_span_sweeper,
start => {otel_span_sweeper, start_link, [SweeperConfig]},
restart => permanent,
shutdown => 5000,
type => worker,
modules => [ot_span_sweeper]},
modules => [otel_span_sweeper]},
SpanHandler = #{id => ot_span_ets,
start => {ot_span_ets, start_link, [[]]},
SpanHandler = #{id => otel_span_ets,
start => {otel_span_ets, start_link, [[]]},
restart => permanent,
shutdown => 5000,
type => worker,
modules => [ot_span_ets]},
modules => [otel_span_ets]},
ChildSpecs = [SpanHandler, Sweeper],
{ok, {SupFlags, ChildSpecs}}.

View File

@ -17,7 +17,7 @@
%% period of time.
%% @end
%%%-------------------------------------------------------------------------
-module(ot_span_sweeper).
-module(otel_span_sweeper).
-behaviour(gen_statem).
@ -32,27 +32,28 @@
-export([storage_size/0]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("ot_span_ets.hrl").
-include("ot_tracer.hrl").
-include("ot_span.hrl").
-include("otel_span_ets.hrl").
-include("otel_tracer.hrl").
-include("otel_span.hrl").
-include_lib("kernel/include/logger.hrl").
-include_lib("opentelemetry_api/include/gradualizer.hrl").
-record(data, {interval :: integer() | infinity,
strategy :: drop | end_span | failed_attribute_and_end_span | fun((opentelemetry:span()) -> ok),
ttl :: integer() | infinity,
storage_size :: integer() | infinity}).
storage_size() ->
{ets:info(?SPAN_TAB, size), ets:info(?SPAN_TAB, memory) * erlang:system_info({wordsize, external})}.
{ets:info(?SPAN_TAB, size), ?assert_type(ets:info(?SPAN_TAB, memory), integer()) * erlang:system_info({wordsize, external})}.
start_link(Opts) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
start_link(Config) ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [Config], []).
init([SweeperConfig]) ->
Interval = maps:get(interval, SweeperConfig, timer:minutes(10)),
Strategy = maps:get(strategy, SweeperConfig, drop),
TTL = maps:get(span_ttl, SweeperConfig, timer:minutes(30)),
StorageSize = maps:get(storage_size, SweeperConfig, infinity),
init([#{interval := Interval,
strategy := Strategy,
span_ttl := TTL,
storage_size := StorageSize}]) ->
{ok, ready, #data{interval=Interval,
strategy=Strategy,
ttl=maybe_convert_time_unit(TTL),
@ -136,7 +137,7 @@ sweep_spans(failed_attribute_and_end_span, TTL) ->
%% must have finished without needing to be swept
ok;
[Span=#span{attributes=Attributes}] ->
Span1 = Span#span{attributes=Attributes ++ [{<<"finished_by_sweeper">>, true}]},
Span1 = Span#span{attributes=otel_attributes:set(<<"finished_by_sweeper">>, true, Attributes)},
end_span(Span1)
end
end || SpanId <- ExpiredSpanIds],
@ -162,6 +163,6 @@ expired_match_spec(Time, Return) ->
end_span(Span=#span{tracestate=Tracestate}) ->
%% hack to not lose tracestate when ending without span ctx
Span1 = ot_span_utils:end_span(Span#span{tracestate=Tracestate}),
Span1 = otel_span_utils:end_span(Span#span{tracestate=Tracestate}),
{_, #tracer{on_end_processors=Processors}} = opentelemetry:get_tracer(),
Processors(Span1).

View File

@ -0,0 +1,128 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @private
%%%-------------------------------------------------------------------------
-module(otel_span_utils).
-export([start_span/5,
end_span/1,
end_span/2]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_sampler.hrl").
-include("otel_span.hrl").
-spec start_span(otel_ctx:t(), opentelemetry:span_name(), otel_sampler:t(), otel_id_generator:t(),
otel_span:start_config()) -> {opentelemetry:span_ctx(), opentelemetry:span() | undefined}.
start_span(Ctx, Name, Sampler, IdGenerator, Opts) ->
SpanAttributeCountLimit = otel_span_limits:attribute_count_limit(),
SpanAttributeValueLengthLimit= otel_span_limits:attribute_value_length_limit(),
EventCountLimit = otel_span_limits:event_count_limit(),
LinkCountLimit = otel_span_limits:link_count_limit(),
AttributePerEventLimit = otel_span_limits:attribute_per_event_limit(),
AttributePerLinkLimit = otel_span_limits:attribute_per_link_limit(),
Attributes = otel_attributes:new(maps:get(attributes, Opts),
SpanAttributeCountLimit,
SpanAttributeValueLengthLimit),
Links = otel_links:new(maps:get(links, Opts),
LinkCountLimit,
AttributePerLinkLimit,
SpanAttributeValueLengthLimit),
Events = otel_events:new(EventCountLimit, AttributePerEventLimit, SpanAttributeValueLengthLimit),
Kind = maps:get(kind, Opts),
StartTime = maps:get(start_time, Opts),
new_span(Ctx, Name, Sampler, IdGenerator, StartTime, Kind, Attributes, Events, Links).
new_span(Ctx, Name, Sampler, IdGeneratorModule, StartTime, Kind, Attributes, Events, Links) ->
{NewSpanCtx, ParentSpanId} = new_span_ctx(Ctx, IdGeneratorModule),
TraceId = NewSpanCtx#span_ctx.trace_id,
SpanId = NewSpanCtx#span_ctx.span_id,
{TraceFlags, IsRecording, SamplerAttributes, TraceState} =
sample(Ctx, Sampler, TraceId, Links, Name, Kind, otel_attributes:map(Attributes)),
Span = #span{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState,
start_time=StartTime,
parent_span_id=ParentSpanId,
kind=Kind,
name=Name,
attributes=otel_attributes:set(SamplerAttributes, Attributes),
events=Events,
links=Links,
trace_flags=TraceFlags,
is_recording=IsRecording},
{NewSpanCtx#span_ctx{trace_flags=TraceFlags,
tracestate=TraceState,
is_valid=true,
is_recording=IsRecording}, Span}.
-spec new_span_ctx(otel_ctx:t(), otel_id_generator:t()) ->
{opentelemetry:span_ctx(), opentelemetry:span_id() | undefined}.
new_span_ctx(Ctx, IdGeneratorModule) ->
case otel_tracer:current_span_ctx(Ctx) of
undefined ->
{root_span_ctx(IdGeneratorModule), undefined};
#span_ctx{is_valid=false} ->
{root_span_ctx(IdGeneratorModule), undefined};
ParentSpanCtx=#span_ctx{span_id=ParentSpanId} ->
%% keep the rest of the parent span ctx, simply need to update the span_id
{ParentSpanCtx#span_ctx{span_id=IdGeneratorModule:generate_span_id()}, ParentSpanId}
end.
root_span_ctx(IdGeneratorModule) ->
#span_ctx{trace_id=IdGeneratorModule:generate_trace_id(),
span_id=IdGeneratorModule:generate_span_id(),
is_valid=true,
trace_flags=0}.
%%--------------------------------------------------------------------
%% @doc
%% Set the end time for a span if it hasn't been set before.
%% @end
%%--------------------------------------------------------------------
-spec end_span(opentelemetry:span()) -> opentelemetry:span().
end_span(Span=#span{end_time=undefined,
trace_flags=TraceFlags}) when ?IS_SAMPLED(TraceFlags) ->
end_span(Span, undefined);
end_span(Span) ->
Span.
-spec end_span(#span{}, integer() | undefined) -> opentelemetry:span().
end_span(Span, Timestamp) when is_integer(Timestamp) ->
Span#span{end_time=Timestamp};
end_span(Span, _) ->
Span#span{end_time=opentelemetry:timestamp()}.
%%
sample(Ctx, Sampler, TraceId, Links, SpanName, Kind, Attributes) ->
{Decision, NewAttributes, TraceState} = otel_sampler:should_sample(
Sampler, Ctx, TraceId, Links, SpanName, Kind, Attributes
),
case Decision of
?DROP ->
{0, false, NewAttributes, TraceState};
?RECORD_ONLY ->
{0, true, NewAttributes, TraceState};
?RECORD_AND_SAMPLE ->
{1, true, NewAttributes, TraceState}
end.

View File

@ -0,0 +1,15 @@
%% This record is for the data of a named tracer.
%% The `tracer' contains the modules to use for span creation,
%% the sampler to use at creation time and the processors to
%% run `OnStart' and `OnEnd'.
%% See OpenTelemetry Tracer spec: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/sdk.md#tracer-creation
-record(tracer,
{
module :: module(),
on_start_processors :: fun((otel_ctx:t(), opentelemetry:span()) -> opentelemetry:span()),
on_end_processors :: fun((opentelemetry:span()) -> boolean() | {error, term()}),
sampler :: otel_sampler:t(),
id_generator :: otel_id_generator:t(),
instrumentation_scope :: otel_tracer_server:instrumentation_scope() | undefined
}).
-type tracer() :: #tracer{}.

View File

@ -0,0 +1,54 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc
%% @end
%%%-------------------------------------------------------------------------
-module(otel_tracer_default).
-behaviour(otel_tracer).
-export([start_span/4,
with_span/5]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_tracer.hrl").
-include("otel_span_ets.hrl").
%% @doc Starts an inactive Span and returns its SpanCtx.
-spec start_span(otel_ctx:t(), opentelemetry:tracer(), opentelemetry:span_name(),
otel_span:start_config()) -> opentelemetry:span_ctx().
start_span(Ctx, {_, #tracer{on_start_processors=Processors,
on_end_processors=OnEndProcessors,
sampler=Sampler,
id_generator=IdGeneratorModule,
instrumentation_scope=InstrumentationScope}}, Name, Opts) ->
SpanCtx = otel_span_ets:start_span(Ctx, Name, Sampler, IdGeneratorModule, Opts, Processors, InstrumentationScope),
SpanCtx#span_ctx{span_sdk={otel_span_ets, OnEndProcessors}}.
-spec with_span(otel_ctx:t(), opentelemetry:tracer(), opentelemetry:span_name(),
otel_span:start_config(), otel_tracer:traced_fun(T)) -> T.
with_span(Ctx, Tracer, SpanName, Opts, Fun) ->
SpanCtx = start_span(Ctx, Tracer, SpanName, Opts),
Ctx1 = otel_tracer:set_current_span(Ctx, SpanCtx),
Token = otel_ctx:attach(Ctx1),
try
Fun(SpanCtx)
after
%% passing SpanCtx directly ensures that this `end_span' ends the span started
%% in this function. If spans in `Fun()' were started and not finished properly
%% they will be abandoned and it be up to the `otel_span_sweeper' to eventually remove them.
_ = otel_span_ets:end_span(SpanCtx),
otel_ctx:detach(Token)
end.

View File

@ -0,0 +1,56 @@
%%%------------------------------------------------------------------------
%% Copyright 2022, OpenTelemetry Authors
%% 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.
%%
%% @private
%%%-------------------------------------------------------------------------
-module(otel_tracer_provider_sup).
-behaviour(supervisor).
-export([start_link/0,
start/2,
start/3]).
-export([init/1]).
-define(SERVER, ?MODULE).
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
%% here to support deprecated function `opentelemetry:start_tracer_provider/2'
start(Name, Config) ->
start(Name, otel_resource:create([]), Config).
start(Name, Resource, Config) ->
try
supervisor:start_child(?MODULE, [Name, Resource, Config])
catch
exit:{noproc, _} ->
%% no tracer provider sup is started, the sdk is probably disabled
{error, no_tracer_provider_supervisor}
end.
init([]) ->
SupFlags = #{strategy => simple_one_for_one,
intensity => 1,
period => 5},
TracerServerSup = #{id => otel_tracer_server_sup,
start => {otel_tracer_server_sup, start_link, []},
restart => permanent,
type => supervisor,
modules => [otel_tracer_server_sup]},
{ok, {SupFlags, [TracerServerSup]}}.

View File

@ -0,0 +1,205 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc This module is the SDK's implementation of the TracerProvider. The
%% calls to the server are done from the API module `otel_tracer_provider'.
%% This `gen_server' is started as part of the SDK's supervision tree and
%% registers itself as the default TracerProvider by using the name
%% `otel_tracer_provider' as its name.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_tracer_server).
-behaviour(gen_server).
-export([start_link/5]).
-export([init/1,
handle_call/3,
handle_cast/2,
code_change/1]).
-include_lib("kernel/include/logger.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_tracer.hrl").
-include("otel_span.hrl").
-type instrumentation_scope() :: #instrumentation_scope{}.
-export_type([instrumentation_scope/0]).
-record(state,
{
%% the tracer configuration shared between all named
%% tracers created by this provider
shared_tracer :: tracer() | undefined,
id_generator :: module(),
processors :: [module()],
sampler :: otel_sampler:t(),
resource :: otel_resource:t(),
span_processor_sup :: atom(),
%% list of tracer names to return noop tracers for
deny_list :: [atom() | {atom(), string()}]
}).
-spec start_link(atom(), atom(), atom(), otel_resource:t(), otel_configuration:t()) -> {ok, pid()} | ignore | {error, term()}.
start_link(Name, RegName, SpanProcessorSupRegName, Resource, Config) ->
gen_server:start_link({local, RegName}, ?MODULE, [Name, SpanProcessorSupRegName, Resource, Config], []).
init([Name, SpanProcessorSup, Resource, #{id_generator := IdGeneratorModule,
sampler := SamplerSpec,
processors := Processors,
deny_list := DenyList}]) ->
Sampler = otel_sampler:new(SamplerSpec),
Processors1 = init_processors(SpanProcessorSup, Processors),
Tracer = #tracer{module=otel_tracer_default,
sampler=Sampler,
on_start_processors=on_start(Processors1),
on_end_processors=on_end(Processors1),
id_generator=IdGeneratorModule},
%% TODO: don't do this if its already set?
opentelemetry:set_default_tracer(Name, {otel_tracer_default, Tracer}),
{ok, #state{id_generator=IdGeneratorModule,
resource=Resource,
sampler=Sampler,
deny_list=DenyList,
shared_tracer=Tracer,
span_processor_sup=SpanProcessorSup,
processors=Processors1}}.
handle_call(resource, _From, State=#state{resource=Resource}) ->
{reply, Resource, State};
handle_call({get_tracer, _Name, _Vsn, _SchemaUrl}, _From, State=#state{shared_tracer=undefined}) ->
{reply, {otel_tracer_noop, []}, State};
handle_call({get_tracer, Name, Vsn, SchemaUrl}, _From, State=#state{shared_tracer=Tracer,
deny_list=DenyList})
when Tracer =/= undefined ->
%% TODO: support semver constraints in denylist
case proplists:is_defined(Name, DenyList) of
true ->
{reply, {otel_tracer_noop, []}, State};
false ->
InstrumentationScope = opentelemetry:instrumentation_scope(Name, Vsn, SchemaUrl),
TracerTuple = {Tracer#tracer.module,
Tracer#tracer{instrumentation_scope=InstrumentationScope}},
{reply, TracerTuple, State}
end;
handle_call({get_tracer, InstrumentationScope}, _From, State=#state{shared_tracer=Tracer,
deny_list=_DenyList})
when Tracer =/= undefined ->
{reply, {Tracer#tracer.module,
Tracer#tracer{instrumentation_scope=InstrumentationScope}}, State};
handle_call(force_flush, _From, State=#state{processors=Processors}) ->
Reply = lists:foldl(fun(Processor, Result) ->
case force_flush_(Processor) of
ok ->
Result;
{error, Reason} ->
update_force_flush_error(Reason, Result)
end
end, ok, Processors),
{reply, Reply, State}.
handle_cast(_, State) ->
{noreply, State}.
code_change(State) ->
{ok, State}.
%%
-spec update_force_flush_error(term(), ok | {error, list()}) -> {error, list()}.
update_force_flush_error(Reason, ok) ->
{error, [Reason]};
update_force_flush_error(Reason, {error, List}) ->
{error, [Reason | List]}.
%% TODO: remove after a period of deprecation for processor `set_exporter' functions
%% This is a hack that makes it so there is a known name for the processor if there
%% is only one, like was once guaranteed. This allows functions like `set_exporter'
%% to work. But if there is more than one processor defined or it isn't one of the
%% builtin processors we will not do this hack of adding a name to the config.
init_processors(SpanProcessorSup, [{P, Config}]) when P =:= otel_batch_processor ;
P =:= otel_simple_processor ->
case init_processor(SpanProcessorSup, P, maps:merge(#{name => global}, Config)) of
{true, {_, _}=Processor} ->
[Processor];
_ ->
[]
end;
init_processors(SpanProcessorSup, Processors) ->
init_processors_(SpanProcessorSup, Processors).
init_processors_(_SpanProcessorSup, []) ->
[];
init_processors_(SpanProcessorSup, [{P, Config} | Rest]) ->
case init_processor(SpanProcessorSup, P, Config) of
{true, {_, _}=Processor} ->
[Processor | init_processors_(SpanProcessorSup, Rest)];
_ ->
init_processors_(SpanProcessorSup, Rest)
end.
init_processor(SpanProcessorSup, ProcessorModule, Config) ->
%% start_link is an optional callback for processors
case lists:member({start_link, 1}, ProcessorModule:module_info(exports)) of
true ->
try supervisor:start_child(SpanProcessorSup,
[ProcessorModule,
%% use a unique reference to distinguish multiple processors of the same type while
%% still having a single name, instead of a possibly changing pid, to
%% communicate with the processor
maps:merge(#{name => erlang:ref_to_list(erlang:make_ref())},
Config)])
of
{ok, _Pid, Config1} ->
{true, {ProcessorModule, Config1}};
{error, Reason} ->
?LOG_INFO("Dropping span processor ~p because `processor_init/1` failed ~p", [ProcessorModule, Reason]),
false
catch
C:T:S ->
?LOG_DEBUG("Dropping span processor ~p because `processor_init/1` threw an exception ~p:~p:~p", [ProcessorModule, C, T, S]),
?LOG_INFO("Dropping span processor ~p because `processor_init/1` threw an exception ~p:~p", [ProcessorModule, C, T]),
false
end;
false ->
{true, {ProcessorModule, Config}}
end.
on_start(Processors) ->
fun(Ctx, Span) ->
lists:foldl(fun({P, Config}, Acc) ->
P:on_start(Ctx, Acc, Config)
end, Span, Processors)
end.
on_end(Processors) ->
fun(Span) ->
lists:foldl(fun({P, Config}, Bool) ->
Bool andalso P:on_end(Span, Config) =:= true
end, true, Processors)
end.
force_flush_({Processor, Config}) ->
try
Processor:force_flush(Config)
catch
C:T ->
{error, {Processor, {C, T}}}
end.

View File

@ -0,0 +1,61 @@
%%%------------------------------------------------------------------------
%% Copyright 2022, OpenTelemetry Authors
%% 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.
%%
%% @private
%%%-------------------------------------------------------------------------
-module(otel_tracer_server_sup).
-behaviour(supervisor).
-export([start_link/3]).
-export([init/1]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
start_link(Name, Resource, Opts) ->
supervisor:start_link(?MODULE, [Name, Resource, Opts]).
init([Name, Resource, Opts]) ->
SupFlags = #{strategy => one_for_one,
intensity => 1,
period => 5},
%% the name of the span tracer provider is used to distinguish span processor
%% supervisors and the tracer provider itself.
%% in the case of the global provider the name is `global'
SpanProcessorSupRegName = list_to_atom(lists:concat([otel_span_processor_sup, "_", Name])),
TracerServeRegName = list_to_atom(lists:concat([otel_tracer_provider, "_", Name])),
SpanProcessorSup = #{id => otel_span_processor_sup,
start => {otel_span_processor_sup, start_link, [SpanProcessorSupRegName]},
restart => permanent,
shutdown => 5000,
type => supervisor,
modules => [otel_span_processor_sup, otel_span_processor]},
TracerServer = #{id => otel_tracer_server,
start => {otel_tracer_server, start_link, [Name,
TracerServeRegName,
SpanProcessorSupRegName,
Resource,
Opts]},
restart => permanent,
shutdown => 5000,
type => worker,
modules => [otel_tracer_provider, otel_tracer_server]},
ChildSpecs = [SpanProcessorSup, TracerServer],
{ok, {SupFlags, ChildSpecs}}.

View File

@ -0,0 +1,53 @@
%% sampler returns `DROP' if a span attribute matches the configured attribute map
%% otherwise `RECORD_AND_SAMPLE'
-module(attributes_sampler).
-behavior(otel_sampler).
-export([description/1,
setup/1,
should_sample/7]).
-include("otel_sampler.hrl").
setup(Attributes) when is_map(Attributes) ->
Attributes;
setup(_) ->
#{}.
description(_) ->
<<"AttributesSampler">>.
-spec should_sample(Ctx, TraceId, Links, SpanName, SpanKind, Attributes, Config) -> Result
when Ctx :: otel_ctx:t(),
TraceId :: opentelemetry:trace_id(),
Links :: otel_links:t(),
SpanName :: opentelemetry:span_name(),
SpanKind :: nopentelemetry:span_kind(),
Attributes :: opentelemetry:attributes_map(),
Config :: otel_sampler:sampler_config(),
Result :: otel_sampler:sampling_result().
should_sample(_Ctx, _TraceId, _Links, _SpanName, _SpanKind, Attributes, ConfigAttributes) ->
case has_match(Attributes, ConfigAttributes) of
true ->
{?DROP, [], []};
_ ->
{?RECORD_AND_SAMPLE, [], []}
end.
has_match(A, B) ->
{Min, Max} = if
map_size(A) < map_size(B) ->
{A, B};
true ->
{B, A}
end,
I = maps:iterator(Min),
has_match_(maps:next(I), Max).
has_match_(none, _) ->
false;
has_match_({K, V, _I}, B) when map_get(K, B) =:= V ->
true;
has_match_({_K, _V, I}, B) ->
has_match_(maps:next(I), B).

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
-module(otel_batch_processor_SUITE).
-compile(export_all).
-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include("otel_span.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
all() ->
[exporting_timeout_test,
check_table_size_test,
exporting_runner_timeout_test].
%% verifies that after the runner has to be killed for taking too long
%% that everything is still functional and the exporter does not crash
exporting_timeout_test(_Config) ->
process_flag(trap_exit, true),
{ok, Pid, _} = otel_batch_processor:start_link(#{name => test_processor,
resource => otel_resource:create([]),
exporter => ?MODULE,
exporting_timeout_ms => 1,
scheduled_delay_ms => 1}),
receive
{'EXIT', Pid, _} ->
%% test is to ensure we don't hit this
ct:fail(batch_processor_crash)
after
100 ->
ok
end.
check_table_size_test(_Config) ->
MaxQueueSize = 10,
CheckTableSizeMs = 1,
{ok, _Pid, #{reg_name := RegName}} = otel_batch_processor:start_link(
#{name => test_processor_check_size_test,
resource => otel_resource:create([]),
exporter => ?MODULE,
exporting_timeout_ms => timer:minutes(10),
%% long enough, so that it never happens during the test
scheduled_delay_ms => timer:minutes(10),
check_table_size_ms => CheckTableSizeMs,
max_queue_size => MaxQueueSize}
),
%% max_queue_size limit is not reached
true = otel_batch_processor:on_end(generate_span(), #{reg_name => RegName}),
lists:foreach(fun(_) ->
otel_batch_processor:on_end(generate_span(), #{reg_name => RegName})
end,
lists:seq(1, MaxQueueSize)),
%% Wait for more than CheckTablesizeMS to be sure check timeout occurred
timer:sleep(CheckTableSizeMs * 5),
dropped = otel_batch_processor:on_end(generate_span(), #{reg_name => RegName}),
otel_batch_processor:force_flush(#{reg_name => RegName}),
%% force_flush is async, have to wait for some long enough time again,
timer:sleep(CheckTableSizeMs * 10),
true = otel_batch_processor:on_end(generate_span(), #{reg_name => RegName}).
exporting_runner_timeout_test(_Config) ->
process_flag(trap_exit, true),
{ok, Pid, #{reg_name := RegName}} = otel_batch_processor:start_link(
#{name => test_processor1,
resource => otel_resource:create([]),
exporter => ?MODULE,
exporting_timeout_ms => 1,
scheduled_delay_ms => 1}),
%% Insert a few spans to make sure runner process will be spawned and killed
%% because it hangs for 10 minutes (see export/4 below)
true = otel_batch_processor:on_end(generate_span(), #{reg_name => RegName}),
true = otel_batch_processor:on_end(generate_span(), #{reg_name => RegName}),
receive
{'EXIT', Pid, _} ->
%% test is to ensure we don't hit this
ct:fail(batch_processor_crash)
after
200 ->
ok
end.
%% exporter behaviour
init(_) ->
{ok, []}.
export(_, _, _, _) ->
timer:sleep(timer:minutes(10)).
shutdown(_) ->
ok.
%% helpers
generate_span() ->
#span{trace_id = otel_id_generator:generate_trace_id(),
span_id = otel_id_generator:generate_span_id(),
name = "test_span",
trace_flags = 1,
is_recording = true,
instrumentation_scope = #instrumentation_scope{name = "test"}}.

View File

@ -0,0 +1,420 @@
-module(otel_configuration_SUITE).
-compile(export_all).
-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include("otel_span.hrl").
-define(assertIsSubset(X, Y),
lists:foreach(fun({K, V}) ->
V1 = proplists:get_value(K, Y, undefined),
%% include the key in the assert so it is there
%% in the error message if it fails
?assertEqual({K, V}, {K, V1})
end, X)).
all() ->
[empty_os_environment, sampler, sampler_parent_based, sampler_parent_based_zero,
sampler_trace_id, sampler_trace_id_default, sampler_parent_based_one,
log_level, propagators, propagators_b3, propagators_b3multi, otlp_exporter,
jaeger_exporter, zipkin_exporter, none_exporter, app_env_exporter,
otlp_metrics_exporter, none_metrics_exporter, span_limits, bad_span_limits,
bad_app_config, deny_list, resource_detectors, span_processors].
init_per_testcase(empty_os_environment, Config) ->
Vars = [],
[{os_vars, Vars} | Config];
init_per_testcase(log_level, Config) ->
Vars = [{"OTEL_LOG_LEVEL", "error"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(propagators, Config) ->
Vars = [{"OTEL_PROPAGATORS", "baggage,afakeone"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(propagators_b3, Config) ->
Vars = [{"OTEL_PROPAGATORS", "b3"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(propagators_b3multi, Config) ->
Vars = [{"OTEL_PROPAGATORS", "b3multi"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(sampler, Config) ->
Vars = [{"OTEL_TRACES_SAMPLER", "parentbased_always_off"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(sampler_trace_id, Config) ->
Vars = [{"OTEL_TRACES_SAMPLER", "traceidratio"},
{"OTEL_TRACES_SAMPLER_ARG", "0.5"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(sampler_trace_id_default, Config) ->
Vars = [{"OTEL_TRACES_SAMPLER", "traceidratio"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(sampler_parent_based, Config) ->
Vars = [{"OTEL_TRACES_SAMPLER", "parentbased_traceidratio"},
{"OTEL_TRACES_SAMPLER_ARG", "0.5"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(sampler_parent_based_one, Config) ->
Vars = [{"OTEL_TRACES_SAMPLER", "parentbased_traceidratio"},
{"OTEL_TRACES_SAMPLER_ARG", "1"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(sampler_parent_based_zero, Config) ->
Vars = [{"OTEL_TRACES_SAMPLER", "parentbased_traceidratio"},
{"OTEL_TRACES_SAMPLER_ARG", "0"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(otlp_exporter, Config) ->
Vars = [{"OTEL_TRACES_EXPORTER", "otlp"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(zipkin_exporter, Config) ->
Vars = [{"OTEL_TRACES_EXPORTER", "zipkin"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(jaeger_exporter, Config) ->
Vars = [{"OTEL_TRACES_EXPORTER", "jaeger"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(none_exporter, Config) ->
Vars = [{"OTEL_TRACES_EXPORTER", "none"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(otlp_metrics_exporter, Config) ->
Vars = [{"OTEL_METRICS_EXPORTER", "otlp"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(none_metrics_exporter, Config) ->
Vars = [{"OTEL_METRICS_EXPORTER", "none"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(deny_list, Config) ->
Vars = [{"OTEL_DENY_LIST", "opentelemetry_exporter,opentelemetry,nonexisting_atom"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(resource_detectors, Config) ->
Vars = [{"OTEL_RESOURCE_DETECTORS", "opentelemetry_exporter,opentelemetry,nonexisting_atom"}],
setup_env(Vars),
[{os_vars, Vars} | Config];
init_per_testcase(span_limits, Config) ->
Vars = [{"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", "111"},
{"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", "009"},
{"OTEL_SPAN_EVENT_COUNT_LIMIT", "200"},
{"OTEL_SPAN_LINK_COUNT_LIMIT", "1101"},
{"OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", "400"},
{"OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", "500"}],
setup_env(Vars),
ExpectedOpts = #{attribute_count_limit => 111,
attribute_value_length_limit => 9,
event_count_limit => 200,
link_count_limit => 1101,
attribute_per_event_limit => 400,
attribute_per_link_limit => 500},
ExpectedRecord = #span_limits{attribute_count_limit=111,
attribute_value_length_limit=9,
event_count_limit=200,
link_count_limit=1101,
attribute_per_event_limit=400,
attribute_per_link_limit=500},
[{expected_opts, ExpectedOpts}, {expected_record, ExpectedRecord}, {os_vars, Vars} | Config];
init_per_testcase(bad_span_limits, Config) ->
Vars = [{"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", "aaa"},
{"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", "bbb"},
{"OTEL_SPAN_EVENT_COUNT_LIMIT", "1d4"},
{"OTEL_SPAN_LINK_COUNT_LIMIT", "eee"},
{"OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", "$L%"},
{"OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", "gibberish"}],
setup_env(Vars),
ExpectedOpts = #{},
ExpectedRecord = #span_limits{attribute_count_limit=128,
attribute_value_length_limit=infinity,
event_count_limit=128,
link_count_limit=128,
attribute_per_event_limit=128,
attribute_per_link_limit=128},
[{expected_opts, ExpectedOpts}, {expected_record, ExpectedRecord}, {os_vars, Vars} | Config];
init_per_testcase(bad_app_config, Config) ->
[{os_vars, []} | Config];
init_per_testcase(app_env_exporter, Config) ->
[{os_vars, []} | Config];
init_per_testcase(span_processors, Config) ->
[{os_vars, []} | Config].
end_per_testcase(_, Config) ->
Vars = ?config(os_vars, Config),
[os:unsetenv(Name) || {Name, _} <- Vars],
ok.
empty_os_environment(_Config) ->
?assertMatch(#{log_level := info,
text_map_propagators := [trace_context, baggage],
sampler := {parent_based, #{root := always_on}}},
otel_configuration:merge_with_os([])),
?assertMatch(#{log_level := error},
otel_configuration:merge_with_os([{log_level, error}])),
ok.
sampler(_Config) ->
?assertMatch({parent_based, #{root := always_off}},
maps:get(sampler, otel_configuration:merge_with_os([]))),
ok.
sampler_parent_based(_Config) ->
?assertMatch({parent_based, #{root := {trace_id_ratio_based, 0.5}}},
maps:get(sampler, otel_configuration:merge_with_os([]))),
ok.
sampler_trace_id(_Config) ->
?assertMatch({trace_id_ratio_based, 0.5},
maps:get(sampler, otel_configuration:merge_with_os([]))),
ok.
sampler_trace_id_default(_Config) ->
?assertMatch({trace_id_ratio_based, 1.0},
maps:get(sampler, otel_configuration:merge_with_os([]))),
ok.
sampler_parent_based_one(_Config) ->
?assertMatch({parent_based, #{root := {trace_id_ratio_based, 1.0}}},
maps:get(sampler, otel_configuration:merge_with_os([]))),
ok.
sampler_parent_based_zero(_Config) ->
?assertMatch({parent_based, #{root := {trace_id_ratio_based, +0.0}}},
maps:get(sampler, otel_configuration:merge_with_os([]))),
ok.
log_level(_Config) ->
?assertMatch(#{log_level := error}, otel_configuration:merge_with_os([])),
?assertMatch(#{log_level := error}, otel_configuration:merge_with_os([{log_level, info}])),
ok.
propagators(_Config) ->
?assertMatch(#{log_level := error,
text_map_propagators := [baggage]},
otel_configuration:merge_with_os([{log_level, error}])),
ok.
propagators_b3(_Config) ->
?assertMatch(#{log_level := error,
text_map_propagators := [b3]},
otel_configuration:merge_with_os([{log_level, error}])),
ok.
propagators_b3multi(_Config) ->
?assertMatch(#{log_level := error,
text_map_propagators := [b3multi]},
otel_configuration:merge_with_os([{log_level, error}])),
ok.
otlp_exporter(_Config) ->
?assertMatch({opentelemetry_exporter, #{}},
maps:get(traces_exporter, otel_configuration:merge_with_os([]))),
ok.
jaeger_exporter(_Config) ->
?assertMatch(none,
maps:get(traces_exporter, otel_configuration:merge_with_os([]))),
ok.
zipkin_exporter(_Config) ->
?assertMatch(none,
maps:get(traces_exporter, otel_configuration:merge_with_os([]))),
ok.
none_exporter(_Config) ->
?assertMatch(none,
maps:get(traces_exporter, otel_configuration:merge_with_os([]))),
?assertMatch(#{processors := [{otel_simple_processor, #{exporter := none}}]},
otel_configuration:merge_with_os([{span_processor, simple}])),
?assertMatch(#{processors := [{otel_batch_processor, #{exporter := none}}]},
otel_configuration:merge_with_os([{span_processor, batch}])),
ok.
app_env_exporter(_Config) ->
?assertMatch({someother_exporter, #{}},
maps:get(traces_exporter,
otel_configuration:merge_with_os([{traces_exporter, {someother_exporter, #{}}}]))),
?assertMatch({opentelemetry_exporter, #{}},
maps:get(traces_exporter,
otel_configuration:merge_with_os([{traces_exporter, otlp}]))),
?assertMatch(none,
maps:get(traces_exporter,
otel_configuration:merge_with_os([{traces_exporter, jaeger}]))),
?assertMatch(none,
maps:get(traces_exporter,
otel_configuration:merge_with_os([{traces_exporter, zipkin}]))),
ok.
otlp_metrics_exporter(_Config) ->
?assertMatch({opentelemetry_exporter, #{}},
maps:get(metrics_exporter, otel_configuration:merge_with_os([]))),
ok.
none_metrics_exporter(_Config) ->
?assertMatch(none,
maps:get(metrics_exporter, otel_configuration:merge_with_os([]))),
ok.
deny_list(_Config) ->
%% nonexisting_atom in the OTEL_DENY_LIST os var is dropped bc it isn't an existing atom
?assertMatch(#{deny_list := [opentelemetry_exporter,opentelemetry]},
otel_configuration:merge_with_os([])),
ok.
resource_detectors(_Config) ->
%% nonexisting_atom in the OTEL_RESOURCE_DETECTORS os var is dropped bc it isn't an existing atom
?assertMatch(#{resource_detectors := [opentelemetry_exporter,opentelemetry]},
otel_configuration:merge_with_os([])),
ok.
span_limits(Config) ->
compare_span_limits(Config).
bad_span_limits(Config) ->
compare_span_limits(Config).
bad_app_config(_Config) ->
?assertMatch(#{attribute_value_length_limit := infinity},
otel_configuration:merge_with_os([{attribute_value_length_limit, "aaa"}])),
ok.
compare_span_limits(Config) ->
ExpectedRecord = ?config(expected_record, Config),
ExpectedOpts = maps:to_list(?config(expected_opts, Config)),
Opts = maps:to_list(otel_configuration:merge_with_os([])),
?assertIsSubset(ExpectedOpts, Opts),
otel_span_limits:set(maps:from_list(Opts)),
SpanLimits = otel_span_limits:get(),
%% verifies the defaults because the base record has the defaults set as well
?assertEqual(ExpectedRecord, SpanLimits),
ok.
span_processors(_Config) ->
?assertMatch(#{processors := [{otel_simple_processor, #{}}]},
otel_configuration:merge_with_os([{span_processor, simple}])),
?assertMatch(#{processors := [{otel_batch_processor, #{exporter := {opentelemetry_exporter,#{}},
exporting_timeout_ms := 2,
max_queue_size := 1,
scheduled_delay_ms := 15000}}]},
otel_configuration:merge_with_os([{span_processor, batch},
{bsp_scheduled_delay_ms, 15000},
{bsp_exporting_timeout_ms, 2},
{bsp_max_queue_size, 1}])),
?assertMatch(#{processors := [{otel_batch_processor, #{exporter := none}}]},
otel_configuration:merge_with_os([{span_processor, batch},
{traces_exporter, none}])),
?assertMatch(#{processors := [{otel_batch_processor, #{exporter := {opentelemetry_exporter,#{}},
exporting_timeout_ms := 30000,
max_queue_size := 2048,
scheduled_delay_ms := 5000}}]},
otel_configuration:merge_with_os([{span_processor, batch}])),
?assertMatch(#{processors := [{otel_batch_processor, #{exporter := {opentelemetry_exporter,
#{endpoints := ["https://example.com"]}},
exporting_timeout_ms := 2,
max_queue_size := 1,
scheduled_delay_ms := 15000}}]},
otel_configuration:merge_with_os([{processors, [{otel_batch_processor, #{exporter => {opentelemetry_exporter,#{endpoints => ["https://example.com"]}},
scheduled_delay_ms => 15000,
max_queue_size => 4,
exporting_timeout_ms => 3}}]},
{bsp_exporting_timeout_ms, 2},
{bsp_max_queue_size, 1}])),
?assertMatch(#{processors := [{otel_simple_processor, #{exporter := {opentelemetry_exporter,#{}},
exporting_timeout_ms := 2}}]},
otel_configuration:merge_with_os([{span_processor, simple},
{ssp_exporting_timeout_ms, 2}])),
ok.
%%
setup_env(Vars) ->
[os:putenv(Name, Value) || {Name, Value} <- Vars].

View File

@ -0,0 +1,201 @@
-module(otel_propagation_SUITE).
-compile(export_all).
-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include_lib("opentelemetry_api/include/otel_tracer.hrl").
-include("otel_tracer.hrl").
-include("otel_span.hrl").
-include("otel_test_utils.hrl").
-include("otel_sampler.hrl").
-include("otel_span_ets.hrl").
all() ->
[override_propagators,
{group, w3c},
{group, b3multi},
{group, b3}].
groups() ->
[{w3c, [], [propagation]},
{b3multi, [], [propagation]},
{b3, [], [propagation]}].
init_per_suite(Config) ->
application:load(opentelemetry),
application:set_env(opentelemetry, processors, [{otel_batch_processor, #{scheduled_delay_ms => 1,
exporter => none}}]),
{ok, _} = application:ensure_all_started(opentelemetry),
Config.
end_per_suite(_Config) ->
application:unload(opentelemetry),
ok.
init_per_group(Propagator, Config) when Propagator =:= w3c ;
Propagator =:= b3multi ;
Propagator =:= b3 ->
%% start in group as well since we must stop it after each group run
{ok, _} = application:ensure_all_started(opentelemetry),
case Propagator of
w3c ->
CompositePropagator = otel_propagator_text_map_composite:create([baggage, trace_context]),
opentelemetry:set_text_map_propagator(CompositePropagator);
b3multi ->
CompositePropagator = otel_propagator_text_map_composite:create([baggage, b3multi]),
opentelemetry:set_text_map_propagator(CompositePropagator);
b3 ->
CompositePropagator = otel_propagator_text_map_composite:create([baggage, b3]),
opentelemetry:set_text_map_propagator(CompositePropagator)
end,
[{propagator, Propagator} | Config].
end_per_group(_, _Config) ->
_ = application:stop(opentelemetry).
propagation(Config) ->
Propagator = ?config(propagator, Config),
SpanCtx=#span_ctx{trace_id=TraceId,
span_id=SpanId} = ?start_span(<<"span-1">>),
?set_current_span(SpanCtx),
?assertMatch(#span_ctx{trace_flags=1}, ?current_span_ctx),
?assertMatch(#span_ctx{is_recording=true}, ?current_span_ctx),
otel_baggage:set("key-1", <<"value=1">>, []),
%% TODO: should the whole baggage entry be dropped if metadata is bad?
%% drop bad metadata (the `1').
otel_baggage:set(<<"key-2">>, <<"value-2">>, [<<"metadata">>, 1, {<<"md-k-1">>, <<"md-v-1">>}]),
%% drop baggage with bad value
otel_baggage:set(<<"key-3">>, value3),
Headers = otel_propagator_text_map:inject([{<<"existing-header">>, <<"I exist">>}]),
EncodedTraceId = io_lib:format("~32.16.0b", [TraceId]),
EncodedSpanId = io_lib:format("~16.16.0b", [SpanId]),
?assertListsEqual([{<<"baggage">>, <<"key-2=value-2;metadata;md-k-1=md-v-1,key-1=value%3D1">>},
{<<"existing-header">>, <<"I exist">>} |
trace_context(Propagator, EncodedTraceId, EncodedSpanId)], Headers),
otel_span:end_span(SpanCtx),
?assertEqual(#{<<"key-1">> => {<<"value=1">>, []},
<<"key-2">> => {<<"value-2">>, [<<"metadata">>, {<<"md-k-1">>, <<"md-v-1">>}]}},
otel_baggage:get_all()),
%% ?end_span doesn't remove the span from the context
?assertEqual(SpanCtx, ?current_span_ctx),
?set_current_span(undefined),
?assertEqual(undefined, ?current_span_ctx),
%% clear our baggage from the context to test extraction
otel_baggage:clear(),
?assertEqual(#{}, otel_baggage:get_all()),
%% make header keys uppercase to validate the extractor is case insensitive
BinaryHeaders = [{string:uppercase(Key), iolist_to_binary(Value)} || {Key, Value} <- Headers],
otel_propagator_text_map:extract(BinaryHeaders),
?assertEqual(#{<<"key-1">> => {<<"value=1">>, []},
<<"key-2">> => {<<"value-2">>, [<<"metadata">>, {<<"md-k-1">>, <<"md-v-1">>}]}},
otel_baggage:get_all()),
%% extracted remote spans are set to the active span
%% but with `is_recording' false
?assertMatch(#span_ctx{is_recording=false}, ?current_span_ctx),
#span_ctx{trace_id=TraceId2,
span_id=_SpanId2} = ?start_span(<<"span-2">>),
%% new span should be a child of the extracted span
?assertEqual(TraceId, TraceId2),
ok.
override_propagators(_Config) ->
SpanCtx=#span_ctx{} = ?start_span(<<"span-1">>),
?set_current_span(SpanCtx),
?assertMatch(#span_ctx{trace_flags=1}, ?current_span_ctx),
?assertMatch(#span_ctx{is_recording=true}, ?current_span_ctx),
otel_baggage:set("key-1", <<"value=1">>, []),
%% TODO: should the whole baggage entry be dropped if metadata is bad?
%% drop bad metadata (the `1').
otel_baggage:set(<<"key-2">>, <<"value-2">>, [<<"metadata">>, 1, {<<"md-k-1">>, <<"md-v-1">>}]),
%% drop baggage with bad value
otel_baggage:set(<<"key-3">>, value3),
Headers = otel_propagator_text_map:inject({otel_propagator_baggage, []}, [{<<"existing-header">>, <<"I exist">>}]),
%% the manually set propagators does not include trace_context or b3multi
%% so header must only have the existing-header and the baggage
?assertListsEqual([{<<"baggage">>, <<"key-2=value-2;metadata;md-k-1=md-v-1,key-1=value%3D1">>},
{<<"existing-header">>, <<"I exist">>}], Headers),
otel_span:end_span(SpanCtx),
?assertEqual(#{<<"key-1">> => {<<"value=1">>, []},
<<"key-2">> => {<<"value-2">>, [<<"metadata">>, {<<"md-k-1">>, <<"md-v-1">>}]}},
otel_baggage:get_all()),
%% ?end_span doesn't remove the span from the context
?assertEqual(SpanCtx, ?current_span_ctx),
?set_current_span(undefined),
?assertEqual(undefined, ?current_span_ctx),
%% clear our baggage from the context to test extraction
otel_baggage:clear(),
?assertEqual(#{}, otel_baggage:get_all()),
%% make header keys uppercase to validate the extractor is case insensitive
BinaryHeaders = [{string:uppercase(Key), iolist_to_binary(Value)} || {Key, Value} <- Headers],
otel_propagator_text_map:extract({otel_propagator_baggage, []}, BinaryHeaders),
?assertEqual(#{<<"key-1">> => {<<"value=1">>, []},
<<"key-2">> => {<<"value-2">>, [<<"metadata">>, {<<"md-k-1">>, <<"md-v-1">>}]}},
otel_baggage:get_all()),
%% no trace extractor used so current span ctx remains undefined
?assertEqual(undefined, ?current_span_ctx),
ok.
%%
assert_all_exported(Tid, SpanCtxs) ->
[assert_exported(Tid, SpanCtx) || SpanCtx <- SpanCtxs].
assert_exported(Tid, #span_ctx{trace_id=TraceId,
span_id=SpanId}) ->
?UNTIL_NOT_EQUAL([], ets:match_object(Tid, #span{trace_id=TraceId,
span_id=SpanId,
_='_'})).
assert_not_exported(Tid, #span_ctx{trace_id=TraceId,
span_id=SpanId}) ->
%% sleep so exporter has run before we check
%% since we can't do like when checking it exists with UNTIL
timer:sleep(100),
?assertMatch([], ets:match(Tid, #span{trace_id=TraceId,
span_id=SpanId,
_='_'})).
trace_context(w3c, EncodedTraceId, EncodedSpanId) ->
[{<<"traceparent">>,
iolist_to_binary([<<"00">>, "-", EncodedTraceId,"-", EncodedSpanId, "-", <<"01">>])}];
trace_context(b3multi, EncodedTraceId, EncodedSpanId) ->
[{<<"X-B3-Sampled">>, <<"1">>},
{<<"X-B3-SpanId">>, iolist_to_binary(EncodedSpanId)},
{<<"X-B3-TraceId">>, iolist_to_binary(EncodedTraceId)}];
trace_context(b3, EncodedTraceId, EncodedSpanId) ->
[{<<"b3">>,
iolist_to_binary([EncodedTraceId, "-", EncodedSpanId, "-", <<"1">>])}].

View File

@ -0,0 +1,386 @@
-module(otel_resource_SUITE).
-compile(export_all).
-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_span.hrl").
-include("otel_test_utils.hrl").
-include("otel_tracer.hrl").
%% TODO: negative testing. What a valid value is is still in flux so nothing bothering
%% to write tests to limit what can be a value only have them become valid values.
all() ->
[startup, startup_env_service_name, os_env_resource, app_env_resource, combining,
combining_conflicting_schemas, crash_detector, timeout_detector, release_service_name,
unknown_service_name, release_service_name_no_version, service_instance_id_env,
service_instance_id_env_attributes, {group, net_kernel_node_name}, service_instance_id_node_id2,
validate_keys, do_not_create_unneeded_atoms].
groups() ->
[{net_kernel_node_name, [], [service_instance_id_node_id1,
service_instance_id_node_name]}].
init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
ok.
init_per_group(net_kernel_node_name, Config) ->
case os:getenv("CI") of
"true" ->
{skip, github_ci};
_ ->
Config
end;
init_per_group(_, Config) ->
Config.
end_per_group(_, _Config) ->
ok.
init_per_testcase(service_instance_id_node_name, Config) ->
start_net_kernel_and_detector([test@instance, shortnames]),
Config;
init_per_testcase(service_instance_id_node_id1, Config) ->
start_net_kernel_and_detector([test@localhost, shortnames]),
Config;
init_per_testcase(_, Config) ->
Config.
end_per_testcase(TestCase, _Config) when TestCase =:= service_instance_id_node_name ;
TestCase =:= service_instance_id_node_id1 ->
net_kernel:stop(),
ok;
end_per_testcase(_, _) ->
ok.
startup(_Config) ->
try
os:putenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=cttest,service.version=1.1.1"),
{ok, _} = application:ensure_all_started(opentelemetry),
Resource = otel_tracer_provider:resource(),
_ = application:stop(opentelemetry),
?assertMatch(#{'service.name' := <<"cttest">>,
'service.version' := <<"1.1.1">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES"),
application:stop(opentelemetry),
application:unload(opentelemetry)
end.
startup_env_service_name(_Config) ->
try
os:putenv("OTEL_SERVICE_NAME", "env-service-name"),
os:putenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=cttest,service.version=1.1.1"),
{ok, _} = application:ensure_all_started(opentelemetry),
Resource = otel_tracer_provider:resource(),
_ = application:stop(opentelemetry),
?assertMatch(#{'service.name' := <<"env-service-name">>,
'service.version' := <<"1.1.1">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("OTEL_SERVICE_NAME"),
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES"),
application:stop(opentelemetry),
application:unload(opentelemetry)
end.
crash_detector(_Config) ->
try
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"c">> => <<"d">>,
"sk" => "sv"}),
os:putenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=cttest,service.version=2.1.1"),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
{otel_resource_detector_test, error},
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.name' := <<"cttest">>,
'service.version' := <<"2.1.1">>,
c := <<"d">>,
sk := <<"sv">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES"),
application:unload(opentelemetry)
end.
timeout_detector(_Config) ->
try
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
os:putenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=cttest,service.version=3.1.1"),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
{otel_resource_detector_test, sleep},
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.name' := <<"cttest">>,
'service.version' := <<"3.1.1">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
?assertEqual(otel_resource:create([]), otel_resource_detector:get_resource(0)),
ok
after
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES"),
application:unload(opentelemetry)
end.
os_env_resource(_Config) ->
Resource = otel_resource_env_var:parse("service.name=cttest,service.version=1.1.1"),
Expected = [{"service.name", "cttest"}, {"service.version", "1.1.1"}],
?assertEqual(Expected, Resource),
ok.
app_env_resource(_Config) ->
Attributes = #{a => [{b,[{c,d}]}], service => #{name => <<"hello">>}},
Expected = [{<<"a.b.c">>, d}, {<<"service.name">>, <<"hello">>}],
%% sort because this is created from a map and need to make sure
%% the order is always the same when we do the assertion
?assertEqual(Expected, lists:sort(otel_resource_app_env:parse(Attributes))),
ok.
combining(_Config) ->
Resource1 = otel_resource:create(otel_resource_app_env:parse([{service, [{name, <<"other-name">>},
{version, "1.1.1"}]}]),
<<"https://opentelemetry.io/schemas/1.8.0">>),
Resource2 = otel_resource:create(otel_resource_env_var:parse("service.name=cttest,service.version=1.1.1"),
<<"https://opentelemetry.io/schemas/1.8.0">>),
Merged = otel_resource:merge(Resource1, Resource2),
Expected = otel_attributes:new([{'service.name', <<"other-name">>},
{'service.version', <<"1.1.1">>}], 128, 255),
?assertEqual(Expected, otel_resource:attributes(Merged)),
?assertEqual(<<"https://opentelemetry.io/schemas/1.8.0">>, otel_resource:schema_url(Merged)),
ok.
combining_conflicting_schemas(_Config) ->
Resource1 = otel_resource:create(otel_resource_app_env:parse([{service, [{name, <<"other-name">>},
{version, "1.1.1"}]}]), <<"https://opentelemetry.io/schemas/1.8.0">>),
Resource2 = otel_resource:create(otel_resource_env_var:parse("service.name=cttest,service.version=1.1.1"),
<<"https://opentelemetry.io/schemas/1.7.0">>),
Merged = otel_resource:merge(Resource1, Resource2),
Expected = otel_attributes:new([{'service.name', <<"other-name">>},
{'service.version', <<"1.1.1">>}], 128, 255),
?assertEqual(Expected, otel_resource:attributes(Merged)),
?assertEqual(undefined, otel_resource:schema_url(Merged)),
ok.
unknown_service_name(_Config) ->
try
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES"),
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.name' := <<"unknown_service:erl">>,
'process.runtime.name' := <<"BEAM">>,
'process.executable.name' := <<"erl">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES")
end.
release_service_name(_Config) ->
try
os:putenv("RELEASE_NAME", "rel-cttest"),
os:putenv("RELEASE_VSN", "0.1.0"),
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.name' := <<"rel-cttest">>,
'service.version' := <<"0.1.0">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("RELEASE_VSN"),
os:unsetenv("RELEASE_NAME")
end.
service_instance_id_env(_Config) ->
try
os:putenv("OTEL_SERVICE_INSTANCE", "test@instance"),
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.instance.id' := <<"test@instance">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("OTEL_SERVICE_INSTANCE")
end.
service_instance_id_env_attributes(_Config) ->
try
os:putenv("OTEL_RESOURCE_ATTRIBUTES", "service.instance.id=test@instance"),
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.instance.id' := <<"test@instance">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok
after
os:unsetenv("OTEL_RESOURCE_ATTRIBUTES")
end.
service_instance_id_node_name(_Config) ->
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.instance.id' := <<"test@instance">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
ok.
service_instance_id_node_id1(_Config) ->
Resource = otel_resource_detector:get_resource(),
ResourceMap = otel_attributes:map(otel_resource:attributes(Resource)),
?assertNotMatch(#{'service.instance.id' := <<"test@localhost">>}, ResourceMap),
?assert(maps:is_key('service.instance.id', ResourceMap)),
ok.
service_instance_id_node_id2(_Config) ->
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
ResourceMap = otel_attributes:map(otel_resource:attributes(Resource)),
?assertNotMatch(#{'service.instance.id' := <<"nonode@nohost">>}, ResourceMap),
?assert(maps:is_key('service.instance.id', ResourceMap)),
ok.
release_service_name_no_version(_Config) ->
try
os:putenv("RELEASE_NAME", "rel-cttest"),
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertMatch(#{'service.name' := <<"rel-cttest">>,
e := <<"f">>}, otel_attributes:map(otel_resource:attributes(Resource))),
?assertNot(maps:is_key('service.version', otel_attributes:map(otel_resource:attributes(Resource)))),
ok
after
os:unsetenv("RELEASE_NAME")
end.
validate_keys(_Config) ->
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{
<<"e">> => <<"f">>,
service => #{
<<"name">> => <<"name">>,
alias => <<"alias">>
},
g => <<"h">>,
'' => <<"i">>,
'ə' => <<"j">>
}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assert(otel_resource:is_key(e, Resource)),
?assert(otel_resource:is_key('service.name', Resource)),
?assert(otel_resource:is_key(<<"service.alias">>, Resource)),
?assert(otel_resource:is_key("service.alias", Resource)),
?assert(otel_resource:is_key('service.alias', Resource)),
?assert(otel_resource:is_key(g, Resource)),
?assertNot(otel_resource:is_key('ə', Resource)),
?assertNot(otel_resource:is_key('', Resource)),
ok.
do_not_create_unneeded_atoms(_Config) ->
NonAtomBinary = fun NonAtomBinaryF(0) ->
error(max_iterations);
NonAtomBinaryF(N) ->
Candidate = << <<($a + rand:uniform(6) - 1)>> || _ <- lists:seq(1,8) >>,
try binary_to_existing_atom(Candidate, latin1) of
_ -> NonAtomBinaryF(N - 1)
catch error:badarg -> Candidate
end
end(100),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_app_env],
resource_detector_timeout => 100}),
Resource = otel_resource_detector:get_resource(),
?assertNot(otel_resource:is_key(NonAtomBinary, Resource)),
?assertError(badarg, binary_to_existing_atom(NonAtomBinary, latin1)),
ok.
%%
start_net_kernel_and_detector(NetKernelArgs) ->
?assertMatch({ok, _}, net_kernel:start(NetKernelArgs)),
application:unload(opentelemetry),
application:load(opentelemetry),
application:set_env(opentelemetry, resource, #{<<"e">> => <<"f">>}),
otel_resource_detector:start_link(#{resource_detectors => [otel_resource_env_var,
otel_resource_app_env],
resource_detector_timeout => 100}),
ok.

View File

@ -0,0 +1,9 @@
-module(otel_resource_detector_test).
-export([get_resource/1]).
get_resource(sleep) ->
timer:sleep(5000),
otel_resource:create([{<<"some-test-resource">>, <<"some-test-value">>}]);
get_resource(error) ->
erlang:error(some_failure).

View File

@ -0,0 +1,345 @@
-module(otel_samplers_SUITE).
-compile(export_all).
-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("otel_sampler.hrl").
all() ->
[trace_id_ratio_based, parent_based, get_description, custom_sampler_module,
custom_attributes_sampler].
init_per_suite(Config) ->
application:load(opentelemetry),
%% set application environment variables
{ok, _} = application:ensure_all_started(opentelemetry),
Config.
end_per_suite(_Config) ->
ok = application:stop(opentelemetry).
init_per_testcase(_, Config) ->
Config.
end_per_testcase(_, _Config) ->
ok.
get_description(_Config) ->
Probability = 0.5,
Sampler = otel_sampler:new({trace_id_ratio_based, Probability}),
?assertEqual(<<"TraceIdRatioBased{0.500000}">>, otel_sampler:description(Sampler)),
ParentBasedSampler = otel_sampler:new(
{parent_based, #{
root => {trace_id_ratio_based, Probability}
}}
),
?assertEqual(
<<"ParentBased{root:TraceIdRatioBased{0.500000},remoteParentSampled:AlwaysOnSampler,remoteParentNotSampled:AlwaysOffSampler,localParentSampled:AlwaysOnSampler,localParentNotSampled:AlwaysOffSampler}">>,
otel_sampler:description(ParentBasedSampler)
),
ok.
trace_id_ratio_based(_Config) ->
SpanName = <<"span-prob-sampled">>,
Probability = 0.5,
DoSample = 120647249294066572380176333851662846319,
DoNotSample = 53020601517903903921384168845238205400,
EmptyTracestate = otel_tracestate:new(),
Ctx = otel_ctx:new(),
%% sampler that runs on all spans
{Sampler, _, Opts} = otel_sampler:new({trace_id_ratio_based, Probability}),
%% checks the trace id is under the upper bound
?assertMatch(
{?RECORD_AND_SAMPLE, [], EmptyTracestate},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, undefined),
DoSample,
[],
SpanName,
undefined,
[],
Opts
)
),
%% checks the trace id is is over the upper bound
?assertMatch(
{?DROP, [], EmptyTracestate},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, undefined),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts
)
),
%% ignores the parent span context trace flags
?assertEqual(
{?DROP, [], otel_tracestate:new()},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{
trace_flags = 1,
is_remote = true
}),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts
)
),
%% ignores the parent span context trace flags
?assertEqual(
{?RECORD_AND_SAMPLE, [], otel_tracestate:new()},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{
trace_flags = 0,
is_remote = false
}),
DoSample,
[],
SpanName,
undefined,
[],
Opts
)
),
%% trace id is under the upper bound
?assertEqual(
{?RECORD_AND_SAMPLE, [], otel_tracestate:new()},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{
trace_flags = 0,
is_remote = true
}),
DoSample,
[],
SpanName,
undefined,
[],
Opts
)
),
ok.
parent_based(_Config) ->
SpanName = <<"span-prob-sampled">>,
Probability = 0.5,
DoSample = 120647249294066572380176333851662846319,
DoNotSample = 53020601517903903921384168845238205400,
EmptyTracestate = otel_tracestate:new(),
Ctx = otel_ctx:new(),
{Sampler, _, Opts} = otel_sampler:new(
{parent_based, #{root => {trace_id_ratio_based, Probability}}}
),
%% with no parent it will run the probability sampler
?assertEqual(
{?RECORD_AND_SAMPLE, [], EmptyTracestate},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, undefined),
DoSample,
[],
SpanName,
undefined,
[],
Opts
)
),
?assertEqual(
{?DROP, [], EmptyTracestate},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, undefined),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts
)
),
%% with parent it will use the parents value
?assertEqual(
{?RECORD_AND_SAMPLE, [], EmptyTracestate},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{
trace_flags = 1,
is_remote = true
}),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts
)
),
?assertEqual(
{?DROP, [], EmptyTracestate},
Sampler:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{
trace_flags = 0,
is_remote = true
}),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts
)
),
%% with no root sampler in setup opts the default sampler always_on is used
{DefaultParentOrElse, _, Opts1} = otel_sampler:new({parent_based, #{}}),
?assertMatch(
{?RECORD_AND_SAMPLE, [], EmptyTracestate},
DefaultParentOrElse:should_sample(
otel_tracer:set_current_span(Ctx, undefined),
DoSample,
[],
SpanName,
undefined,
[],
Opts1
)
),
?assertMatch(
{?RECORD_AND_SAMPLE, [], EmptyTracestate},
DefaultParentOrElse:should_sample(
otel_tracer:set_current_span(Ctx, undefined),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts1
)
),
?assertEqual(
{?RECORD_AND_SAMPLE, [], otel_tracestate:new()},
DefaultParentOrElse:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{trace_flags = 1}),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts1
)
),
?assertEqual(
{?DROP, [], otel_tracestate:new()},
DefaultParentOrElse:should_sample(
otel_tracer:set_current_span(Ctx, #span_ctx{
trace_flags = 0,
is_remote = true
}),
DoNotSample,
[],
SpanName,
undefined,
[],
Opts1
)
),
ok.
custom_sampler_module(_Config) ->
SpanName = <<"span-name">>,
{Sampler, _, Opts} = otel_sampler:new({static_sampler, #{SpanName => ?DROP}}),
?assertMatch(
{?DROP, [], []},
Sampler:should_sample(
otel_ctx:new(),
otel_id_generator:generate_trace_id(),
[],
SpanName,
undefined,
[],
Opts
)
),
ok.
custom_attributes_sampler(_Config) ->
SpanName = <<"span-name">>,
{Sampler, _, Opts} = otel_sampler:new({attributes_sampler, #{'http.target' => <<"/healthcheck">>}}),
?assertMatch(
{?DROP, [], []},
Sampler:should_sample(
otel_ctx:new(),
otel_id_generator:generate_trace_id(),
[],
SpanName,
undefined,
#{'http.target' => <<"/healthcheck">>,
a => b},
Opts
)
),
?assertMatch(
{?RECORD_AND_SAMPLE, [], []},
Sampler:should_sample(
otel_ctx:new(),
otel_id_generator:generate_trace_id(),
[],
SpanName,
undefined,
#{a => 1},
Opts
)
),
?assertMatch(
{?RECORD_AND_SAMPLE, [], []},
Sampler:should_sample(
otel_ctx:new(),
otel_id_generator:generate_trace_id(),
[],
SpanName,
undefined,
#{},
Opts
)
),
ok.
should_sample(_Config) ->
Sampler = otel_sampler:new(always_on),
?assertMatch(
{?RECORD_AND_SAMPLE, [], []},
otel_samplers:should_sample(
Sampler,
otel_ctx:new(),
otel_id_generator:generate_trace_id(),
[],
<<"span-name">>,
undefined,
[]
)
),
ok.

View File

@ -2,19 +2,19 @@
%%% @doc
%%% @end
%%% ---------------------------------------------------------------------------
-module(ot_sweeper_SUITE).
-module(otel_sweeper_SUITE).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
-include("ot_test_utils.hrl").
-include("ot_span.hrl").
-include("otel_test_utils.hrl").
-include("otel_span.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include_lib("opentelemetry_api/include/tracer.hrl").
-include_lib("opentelemetry_api/include/otel_tracer.hrl").
-include("../src/ot_span_ets.hrl").
-include("../src/otel_span_ets.hrl").
all() ->
[storage_size,
@ -28,6 +28,7 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
application:unload(opentelemetry),
application:stop(opentelemetry),
ok.
init_per_testcase(storage_size, Config) ->
@ -35,22 +36,21 @@ init_per_testcase(storage_size, Config) ->
strategy => end_span,
span_ttl => 500,
storage_size => 100}),
application:set_env(opentelemetry, tracer, ot_tracer_default),
application:set_env(opentelemetry, processors, [{ot_batch_processor, #{scheduled_delay_ms => 1}}]),
application:set_env(opentelemetry, tracer, otel_tracer_default),
application:set_env(opentelemetry, processors, [{otel_batch_processor, #{scheduled_delay_ms => 1,
exporter => {otel_exporter_pid, self()}}}]),
{ok, _} = application:ensure_all_started(opentelemetry),
ot_batch_processor:set_exporter(ot_exporter_pid, self()),
Config;
init_per_testcase(Type, Config) ->
application:set_env(opentelemetry, sweeper, #{interval => 250,
strategy => Type,
span_ttl => 500}),
application:set_env(opentelemetry, tracer, ot_tracer_default),
application:set_env(opentelemetry, processors, [{ot_batch_processor, #{scheduled_delay_ms => 1}}]),
application:set_env(opentelemetry, tracer, otel_tracer_default),
application:set_env(opentelemetry, processors, [{otel_batch_processor, #{scheduled_delay_ms => 1,
exporter => {otel_exporter_pid, self()}}}]),
{ok, _} = application:ensure_all_started(opentelemetry),
ot_batch_processor:set_exporter(ot_exporter_pid, self()),
Config.
end_per_testcase(_, _Config) ->
@ -60,9 +60,13 @@ end_per_testcase(_, _Config) ->
storage_size(_Config) ->
SpanName1 = <<"span-1">>,
SpanCtx = ?start_span(SpanName1),
?set_current_span(SpanCtx),
ChildSpanName1 = <<"child-span-1">>,
ChildSpanCtx = ?start_span(ChildSpanName1),
?set_current_span(ChildSpanCtx),
?assertEqual(SpanCtx#span_ctx.trace_id, ChildSpanCtx#span_ctx.trace_id),
[ChildSpanData] = ets:lookup(?SPAN_TAB, ChildSpanCtx#span_ctx.span_id),
?assertEqual(ChildSpanName1, ChildSpanData#span.name),
@ -77,7 +81,7 @@ storage_size(_Config) ->
%% should be no exported spans
?assertEqual(no_span, receive
{span, #span{name=N}} when N =:= SpanName1 ->
got_span
gotel_span
after
0 ->
no_span
@ -86,20 +90,22 @@ storage_size(_Config) ->
drop(_Config) ->
SpanName1 = <<"span-1">>,
SpanCtx = ?start_span(SpanName1),
otel_tracer:set_current_span(SpanCtx),
ChildSpanName1 = <<"child-span-1">>,
ChildSpanCtx = ?start_span(ChildSpanName1),
otel_tracer:set_current_span(ChildSpanCtx),
[ChildSpanData] = ets:lookup(?SPAN_TAB, ChildSpanCtx#span_ctx.span_id),
?assertEqual(ChildSpanName1, ChildSpanData#span.name),
?assertEqual(SpanCtx#span_ctx.span_id, ChildSpanData#span.parent_span_id),
?end_span(),
otel_span:end_span(ChildSpanCtx),
%% wait until the sweeper sweeps away the parent span
?UNTIL(ets:tab2list(?SPAN_TAB) =:= []),
?end_span(),
otel_span:end_span(SpanCtx),
receive
{span, S=#span{name=Name}} when Name =:= ChildSpanName1 ->
@ -116,7 +122,7 @@ drop(_Config) ->
%% should be no exported span for span-1
?assertEqual(no_span, receive
{span, #span{name=N}} when N =:= SpanName1 ->
got_span
gotel_span
after
0 ->
no_span
@ -124,11 +130,14 @@ drop(_Config) ->
end_span(_Config) ->
SpanName1 = <<"span-1">>,
_SpanCtx = ?start_span(SpanName1),
SpanCtx = ?start_span(SpanName1),
otel_tracer:set_current_span(SpanCtx),
ChildSpanName1 = <<"child-span-1">>,
_ChildSpanCtx = ?start_span(ChildSpanName1),
?end_span(),
ChildSpanCtx = ?start_span(ChildSpanName1),
otel_tracer:set_current_span(ChildSpanCtx),
otel_span:end_span(SpanCtx),
%% wait until the sweeper sweeps away the parent span
?UNTIL(ets:tab2list(?SPAN_TAB) =:= []),
@ -147,15 +156,17 @@ end_span(_Config) ->
failed_attribute_and_end_span(_Config) ->
SpanName1 = <<"span-1">>,
SpanCtx = ?start_span(SpanName1),
otel_tracer:set_current_span(SpanCtx),
ChildSpanName1 = <<"child-span-1">>,
ChildSpanCtx = ?start_span(ChildSpanName1),
otel_tracer:set_current_span(ChildSpanCtx),
[ChildSpanData] = ets:lookup(?SPAN_TAB, ChildSpanCtx#span_ctx.span_id),
?assertEqual(ChildSpanName1, ChildSpanData#span.name),
?assertEqual(SpanCtx#span_ctx.span_id, ChildSpanData#span.parent_span_id),
?end_span(),
otel_span:end_span(ChildSpanData),
%% wait until the sweeper sweeps away the parent span
?UNTIL(ets:tab2list(?SPAN_TAB) =:= []),
@ -164,7 +175,7 @@ failed_attribute_and_end_span(_Config) ->
{span, S=#span{name=Name,
attributes=Attributes}} when Name =:= SpanName1 ->
%% should have attribute finished_by_sweeper
?assertMatch([{<<"finished_by_sweeper">>, true}], Attributes),
?assertMatch(#{<<"finished_by_sweeper">> := true}, otel_attributes:map(Attributes)),
%% Verify the end time and duration are set when the span was finished
?assertMatch(ST when is_integer(ST), S#span.start_time),

View File

@ -1,6 +1,6 @@
%% Try for 1 seconds
-define(UNTIL(X), (fun Until(I) when I =:= 10 ->
ct:fail(timeout);
ct:fail("timeout: UNTIL(~s)", [??X]);
Until(I) ->
case X of
true ->
@ -13,7 +13,7 @@
%% try for 1 second and also return the result of Y
-define(UNTIL_NOT_EQUAL(X, Y), (fun Until(I) when I =:= 10 ->
ct:fail(timeout);
ct:fail("timeout: UNTIL_NOT_EQUAL(~s, ~s)", [??X, ??Y]);
Until(I) ->
R = Y,
case X =/= R of
@ -25,7 +25,10 @@
end
end)(0)).
-define(assertListsMatch(List1, List2), ?assertEqual(lists:sort(List1), lists:sort(List2))).
-define(assertListsEqual(List1, List2), ?assertEqual(lists:sort(List1), lists:sort(List2))).
-define(assertIsSubset(List1, List2), ?assertMatch([], sets:to_list(sets:subtract(sets:from_list(List1),
sets:from_list(List2))))).
%% a macro for asserting the important parts of a span ctx are equal
%% parts we keep in the record like is_recording is not propagated and

View File

@ -0,0 +1,14 @@
-module(static_sampler).
-behavior(otel_sampler).
-export([description/1, setup/1, should_sample/7]).
-include("otel_sampler.hrl").
%% sampler returns the value from the Opts map based on the SpanName or `DROP'
setup(Opts) -> Opts.
description(_) -> <<"StaticSampler">>.
should_sample(_, _, _, SpanName, _, _, Config) -> {maps:get(SpanName, Config, ?DROP), [], []}.

View File

@ -0,0 +1,3 @@
[
inputs: ["{mix,.dialyzer_ignore,.formatter}.exs", "{lib,test}/**/*.{ex,exs}"]
]

33
apps/opentelemetry_api/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
edoc
.rebar3
_*
.eunit
*.o
*.beam
*.plt
*.swp
*.swo
.erlang.cookie
ebin
log
erl_crash.dump
.rebar
logs
_build
.idea
*.iml
rebar3.crashdump
*~
/_build
/cover
/deps
/doc
/.fetch
erl_crash.dump
*.ez
*.beam
/config/*.secret.exs
.elixir_ls/
/coverage.xml

View File

@ -0,0 +1,201 @@
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
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,269 @@
# Erlang/Elixir OpenTelemetry API
[![EEF Observability WG project](https://img.shields.io/badge/EEF-Observability-black)](https://github.com/erlef/eef-observability-wg)
[![Hex.pm](https://img.shields.io/hexpm/v/opentelemetry)](https://hex.pm/packages/opentelemetry_api)
This is the API portion of [OpenTelemetry](https://opentelemetry.io/) for Erlang
and Elixir Applications, implementing the API portion of [the specification](https://github.com/open-telemetry/opentelemetry-specification).
This is a library, it does not start any processes, and should be the only
OpenTelemetry dependency of Erlang/Elixir Applications.
## Use
There are both Erlang and Elixir macros that make use of the current module's
name to lookup a [Named
Tracer](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#tracer-name--meter-name)
-- a Named Tracer is created for each Application loaded in the system at start
time -- for you and can be used for Trace and Span operations:
``` erlang
-include_lib("opentelemetry_api/include/otel_tracer.hrl").
some_fun() ->
?with_span(<<"some_fun/0">>, #{},
fun(_SpanCtx) ->
...
?set_attribute(<<"key">>, <<"value">>),
...
end),
```
``` elixir
require OpenTelemetry.Tracer
def some_fun() do
OpenTelemetry.Tracer.with_span "some-span" do
...
OpenTelemetry.Tracer.set_attribute("key", "value")
...
end
end
```
### Tracing API
The macros and functions available for Elixir in `OpenTelemetry.Tracer` and the
Erlang macros in `otel_tracer.hrl` are the best way to work with Spans. They
will automatically use the Tracer named for the Application the module using the
macro is in. For example, the Spans created in
[opentelemetry_oban](https://hex.pm/packages/opentelemetry_oban) use the
`with_span` macro resulting in the Span being created with the
`opentelemetry_oban` named Tracer and associated with the [Instrumentation
Library](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/glossary.md#instrumentation-library)
of the same name and version of the Tracer -- the version also matches the
`opentelemetry_oban` Application version.
#### Context
[Context](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/context/context.md) is used to pass values associated with the current [execution
unit](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/glossary.md#execution-unit).
At this time the only values kept in the Context by this OpenTelemetry library
are the [Span
Context](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#spancontext)
for the currently active Span and the
[Baggage](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/baggage/api.md)
When a Context variable is not an explicit argument in the API macros or
functions the Context from the [process
dictionary](https://www.erlang.org/doc/reference_manual/processes.html#process-dictionary)
is used. If no Context is found in the current process's pdict then one is
created.
#### Starting and Ending Spans
A Span represents a single operation in a Trace. It has a start and end time,
can have a single parent and one or more children. The easiest way to create
Spans is to wrap the operation you want a Span to represent in the `with_span`
macro. The macro handles getting a
[Tracer](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#tracer)
associated with the OTP Application the module is in, starting the Span, setting
it as the currently active Span in the Context stored in the process dictionary
and ending the Span when the `Fun` or body of the Elixir macro finish, even if
an exception is thrown -- however, the exception is not caught, so it does not
change how user code should deal with raised exceptions. After the Span is
ended the Context in the process dictionary is reset to its value before the
newly started Span was set as the active Span. This handling of the active Span
in the process dictionary ensures proper lineage of Spans is kept when starting
and ending child Spans.
``` erlang
?with_span(SpanName, StartOpts, Fun)
```
``` elixir
OpenTelemetry.Tracer.with_span name, start_opts do
...
end
```
`StartOpts`/`start_opts` is a map of [Span creation options](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#span-creation):
- `kind`:
[SpanKind](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#spankind)
defines the relationship between the Span, its parents, and its children in a
Trace. Possible values: `internal`, `server`, `client`, `producer` and
`consumer`. Defaults to `internal` if not specified.
- `attributes`: See
[Attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/common/common.md#attributes)
for details about Attributes. Default is an empty list of attributes.
- `links`: List of [Links](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/overview.md#links-between-spans) to causally related Spans from the same or a different Trace.
- `start_time`: The start time of the Span operation. Defaults to the current
time. The option should only be set if the start of the operation described by
the Span has already passed.
current_span_ctx(ctx)
set_current_span(span_ctx)
When using `start_span` instead of `with_span` there must be a corresponding
call to the [end Span
API](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#end)
to signal that the operation described by the Span has ended. `end_span`
optionally takes a timestamp to use as the end time of the Span.
``` erlang
?end_span()
?end_span(Timestamp)
```
``` elixir
OpenTelemetry.Tracer.end_span(timestamp \\ :undefined)
```
#### Sampling
Sampling is performed at span creation time by the Sampler configured on the Tracer, see [Samplers](https://hexdocs.pm/opentelemetry/readme.html).
To pass attributes for use by the sampler, use the attributes field of `StartOpts`/`start_opts`
example:
``` elixir
OpenTelemetry.Tracer.start_span(span_name, %{attributes: %{my_attribute: "my value"}})
```
#### Setting Attributes
[Setting
Attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-attributes)
can be done with a single key and value passed to `set_attribute` or through a
map of
[Attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/common/common.md#attributes)
all at once. Setting an attribute with a key that already exists in the Span's
map of attributes will result in that key's value being overwritten.
``` erlang
?set_attribute(Key, Value)
?set_attributes(Attributes)
```
``` elixir
OpenTelemetry.Tracer.set_attribute(key, value)
OpenTelemetry.Tracer.set_attributes(attributes)
```
Be aware that there are [configurable limits](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/common/common.md#attribute-limits) on the number and size of
Attributes per Span.
#### Adding Events
[Adding
Events](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#add-events)
can be done by passing the name of the event and the
[Attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/common/common.md#attributes)
to associate with it or as a list of Events. Each Event in the list of Events is
a map containing the timestamp, name, and Attributes which can be created with
the function `event/2` and `event/3` in the `opentelemetry` and `OpenTelemetry`
modules.
``` erlang
?add_event(Name, Attributes)
?add_events(Events)
```
``` elixir
OpenTelemetry.Tracer.add_event(event, attributes)
OpenTelemetry.Tracer.add_events(events)
```
#### Setting the Status
[Set
Status](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-status)
will override the default Span Status of `Unset`. A Status is a code (`ok`,
`error` or `unset`) and, only if the code is `error`, an optional message string
that describes the error.
``` erlang
?set_status(Code, Message)
```
``` elixir
OpenTelemetry.Tracer.set_status(code, message)
```
#### Update Span Name
[Updating the Span
name](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#updatename)
can be done after starting the Span but must be done before the Span is end'ed.
``` erlang
?update_name(Name)
```
``` elixir
OpenTelemetry.Tracer.update_name(name)
```
### Including the OpenTelemetry SDK
When only the API is available at runtime a no-op Tracer is used and no Traces
are exported. The [OpenTelemetry SDK](https://hex.pm/packages/opentelemetry)
provides the functionality of Tracers, Span Processors and Exporters and should
be included as part of a
[Release](https://erlang.org/doc/design_principles/release_structure.html) and
not as a dependency of any individual Application.
### Exporters
Included in the same [Github
repo](https://github.com/open-telemetry/opentelemetry-erlang) as the API and SDK are an exporter for the [OpenTelemetry Protocol
(OTLP)](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/protocol/otlp.md)
and [Zipkin](https://zipkin.io/):
- [OpenTelemetry Protocol](https://hex.pm/packages/opentelemetry_exporter)
- [Zipkin](https://hex.pm/packages/opentelemetry_zipkin)
### Log Correlation
When a Span is made active in a process, for example when the `with_span` macro
is used, it is added to the [logger
metadata](https://www.erlang.org/doc/apps/kernel/logger_chapter.html). The
metadata is under the key `otel_span_ctx`. Example usage:
``` erlang
{kernel,
[{logger_level, debug},
{logger,
[{handler, default, logger_std_h,
#{formatter => {logger_formatter,
#{template => [time, " ", file, ":", line, " ", level, ": ",
{otel_trace_id, ["trace_id=",otel_trace_id," "], []},
{otel_span_id, ["span_id=",otel_span_id," "], []},
msg,"\n"]}}}}]}]}
```
### Integrations
Instrumentations of many popular Erlang and Elixir projects can be found in the
[contrib repo](https://github.com/open-telemetry/opentelemetry-erlang-contrib)
and on [hex.pm](https://hex.pm) under the [OpenTelemetry organization](https://hex.pm/orgs/opentelemetry).
## Contributing
Read OpenTelemetry project [contributing
guide](https://github.com/open-telemetry/community/blob/main/CONTRIBUTING.md)
for general information about the project.

View File

@ -0,0 +1 @@
src/otel_tracer_provider.erl:39:5: Unknown function otel_tracer_provider_sup:start/2

View File

@ -0,0 +1,39 @@
%% Syntax elements for type annotations
%%
%% The macro ?annotate_type/2 can be used to annotate an expression with a
%% type. This is useful to add type annotation after fetching a value from an
%% ets table, received a message on a known form or read from a dict, proplist,
%% process dictionary, etc.
%%
%% The specified type must be compatible with the type detected by Gradualizer.
%% Otherwise a type error is reported.
%%
%% N = ?annotate_type( Message, non_neg_integer() )
%%
%% The macro ?assert_type/2 can be used to refine (downcast) a type propagated
%% by Gradualizer. For example, the programmer may know that the length of a
%% list is within a certain range, rather than any non_neg_integer():
%%
%% Arity = ?assert_type( length(Args), arity() )
%%
%% The functions '::'/2 and ':::'/2 can also be used directly if the type is
%% quoted:
%%
%% N = '::'(Message, "non_neg_integer()")
%%
%% Gradualizer detects occurrences of the functions '::'/2 and ':::'/2 and
%% adjusts type checking accordingly. The macros are supplied only for
%% convenience.
%%
-compile({inline, ['::'/2, ':::'/2]}).
-compile({nowarn_unused_function, ['::'/2, ':::'/2]}).
-ignore_xref(['::'/2, ':::'/2]).
'::'(Expr, _Type) -> Expr.
':::'(Expr, _Type) -> Expr.
%% Type annotation
-define(annotate_type(Expr, Type), '::'(Expr, ??Type)).
%% Refinement (downcast) AKA type assertion
-define(assert_type(Expr, Type), ':::'(Expr, ??Type)).

View File

@ -0,0 +1,80 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%%------------------------------------------------------------------------
%% convert 2 strings (one meant to be like a namespace and the other a unique name)
%% to an atom for use registering a process
-define(REG_NAME(Name), list_to_atom(lists:concat([?MODULE, "_", Name]))).
-define(GLOBAL_TRACER_PROVIDER_NAME, global).
-define(GLOBAL_TRACER_PROVIDER_REG_NAME, otel_tracer_provider_global).
%% These records are based on protos found in the opentelemetry-proto repo:
%% src/opentelemetry/proto/trace/v1/trace.proto
%% They are not exact translations because further processing is done after
%% the span has finished and can be vendor specific. For example, there is
%% no count of the number of dropped attributes in the span record. And
%% an attribute's value can be a function to only evaluate the value if it
%% is actually used (at the time of exporting).
%% for use in guards: sampling bit is the first bit in 8-bit trace options
-define(IS_SAMPLED(TraceFlags), (TraceFlags band 1) =/= 0).
-define(SPAN_KIND_INTERNAL, internal).
-define(SPAN_KIND_SERVER, server).
-define(SPAN_KIND_CLIENT, client).
-define(SPAN_KIND_PRODUCER, producer).
-define(SPAN_KIND_CONSUMER, consumer).
-define(OTEL_STATUS_UNSET, unset).
-define(OTEL_STATUS_OK, ok).
-define(OTEL_STATUS_ERROR, error).
%% Holds information about the instrumentation scope specified when
%% getting a Tracer from the TracerProvider.
-record(instrumentation_scope, {name :: unicode:unicode_binary() | undefined,
version :: unicode:unicode_binary() | undefined,
schema_url :: uri_string:uri_string() | undefined}).
-record(span_ctx, {
%% 128 bit int trace id
trace_id :: opentelemetry:trace_id(),
%% 64 bit int span id
span_id :: opentelemetry:span_id(),
%% 8-bit integer, lowest bit is if it is sampled
trace_flags = 0 :: integer(),
%% Tracestate represents tracing-system specific context in a list of key-value pairs.
%% Tracestate allows different vendors propagate additional information and
%% inter-operate with their legacy Id formats.
tracestate = otel_tracestate:new() :: otel_tracestate:t(),
%% IsValid is a boolean flag which returns true if the SpanContext has a non-zero
%% TraceID and a non-zero SpanID.
is_valid :: boolean() | undefined,
%% true if the span context came from a remote process
%% defaults to false and the propagator must set to true when extracting
is_remote = false :: boolean(),
%% this field is not propagated and is only here as an implementation optimization
%% If true updates like adding events are done on the span. The same as if the
%% trace flags lowest bit is 1 but simply not propagated.
is_recording :: boolean() | undefined,
%% the sdk must put a module to call in the SDK for span operations
%% and include an optional term of configuration it needs
span_sdk :: {module(), term()} | undefined
}).
-record(status, {
code = ?OTEL_STATUS_UNSET :: opentelemetry:status_code(),
%% developer-facing error message
message = <<"">> :: unicode:unicode_binary()
}).

View File

@ -0,0 +1,4 @@
-define(current_ctx, otel_ctx:get_current()).
-define(with_ctx(Ctx, Fun),
otel_ctx:with_ctx(Ctx, Fun)).

View File

@ -0,0 +1,58 @@
%% macros for tracing
%% tracers for applications are automatically created on boot
-define(current_tracer, opentelemetry:get_application_tracer(?MODULE)).
-define(current_span_ctx, otel_tracer:current_span_ctx()).
-define(start_span(SpanName),
otel_tracer:start_span(?current_tracer, SpanName, #{})).
-define(start_span(SpanName, StartOpts),
otel_tracer:start_span(?current_tracer, SpanName, StartOpts)).
-define(with_span(SpanName, Fun),
otel_tracer:with_span(?current_tracer, SpanName, #{}, Fun)).
-define(with_span(SpanName, StartOpts, Fun),
otel_tracer:with_span(?current_tracer, SpanName, StartOpts, Fun)).
-define(set_current_span(SpanCtx),
otel_tracer:set_current_span(SpanCtx)).
%% updates the current context with the updated span context that
%% has `is_recording' set to `false'
-define(end_span(),
?end_span(undefined)).
-define(end_span(Timestamp),
otel_tracer:set_current_span(otel_span:end_span(?current_span_ctx, Timestamp))).
-define(is_recording(),
otel_span:is_recording(?current_span_ctx)).
-define(set_attribute(Key, Value),
otel_span:set_attribute(?current_span_ctx, Key, Value)).
-define(set_attributes(Attributes),
otel_span:set_attributes(?current_span_ctx, Attributes)).
-define(record_exception(Class, Term, Stacktrace, Attributes),
otel_span:record_exception(?current_span_ctx, Class, Term, Stacktrace, Attributes)).
-define(record_exception(Class, Term, Message, Stacktrace, Attributes),
otel_span:record_exception(?current_span_ctx, Class, Term, Message, Stacktrace, Attributes)).
-define(add_event(Name, Attributes),
otel_span:add_event(?current_span_ctx, Name, Attributes)).
-define(add_events(Events),
otel_span:add_events(?current_span_ctx, Events)).
-define(set_status(Code, Message),
otel_span:set_status(?current_span_ctx, Code, Message)).
-define(set_status(StatusOrCode),
otel_span:set_status(?current_span_ctx, StatusOrCode)).
-define(update_name(Name),
otel_span:update_name(?current_span_ctx, Name)).

View File

@ -0,0 +1,215 @@
defmodule OpenTelemetry do
@moduledoc """
An [OpenTelemetry](https://opentelemetry.io) Trace consists of 1 or more Spans that either have a
parent/child relationship or are linked together through a Link. Each Span has a TraceId (`t:trace_id/0`),
SpanId (`t:span_id/0`), and a start and end time in nanoseconds.
This module provides declaration of the types used throughout the library, as well as functions for
building the additional pieces of a span that are optional. Each item can be attached to individual
Span using the functions in `OpenTelemetry.Span` module.
## Example
require OpenTelemetry.Tracer, as: Tracer
Tracer.with_span "some-span" do
event = OpenTelemetry.event("ecto.query", query: query, total_time: total_time)
Tracer.add_events([event])
end
"""
@typedoc """
A SpanContext represents the portion of a Span needed to do operations on a
Span. Within a process it acts as a key for looking up and modifying the
actual Span. It is also what is serialized and propagated across process
boundaries.
"""
@type span_ctx() :: :opentelemetry.span_ctx()
@typedoc """
Span represents a single operation within a trace. Spans can be
nested to form a trace tree. Spans may also be linked to other spans
from the same or different trace and form graphs. Often, a trace
contains a root span that describes the end-to-end latency, and one
or more subspans for its sub-operations. A trace can also contain
multiple root spans, or none at all. Spans do not need to be
contiguous - there may be gaps or overlaps between spans in a trace.
"""
@type span() :: :opentelemetry.span()
@type span_kind() :: :opentelemetry.span_kind()
@type span_name() :: :opentelemetry.span_name()
@typedoc """
TraceId is a unique identifier for a trace. All spans from the same trace share
the same `trace_id`. The ID is a 16-byte array. An ID with all zeroes
is considered invalid.
"""
@type trace_id() :: non_neg_integer()
@typedoc """
SpanId is a unique identifier for a span within a trace, assigned when the span
is created. The ID is an 8-byte array. An ID with all zeroes is considered
invalid.
"""
@type span_id() :: non_neg_integer()
@typedoc """
Hex-encoded TraceId as a 32-character lowercase binary string.
"""
@type hex_trace_id() :: :opentelemetry.hex_trace_id()
@typedoc """
Hex-encoded SpanId as a 16-character lowercase binary string.
"""
@type hex_span_id() :: :opentelemetry.hex_span_id()
@type attribute_key() :: :opentelemetry.attribute_key()
@type attribute_value() :: :opentelemetry.attribute_value()
@typedoc """
Attributes are a collection of key/value pairs. The value can be a string,
an integer, a double or the boolean values `true` or `false`. Note, global attributes
like server name can be set using the resource API.
Examples of attributes:
[{"/http/user_agent" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"}
{"/http/server_latency", 300}
{"abc.com/myattribute", True}
{"abc.com/score", 10.239}]
"""
@type attributes_map() :: :opentelemetry.attributes_map()
@typedoc """
Tracestate represents tracing-system specific context in a list of key-value pairs.
Tracestate allows different vendors propagate additional information and
inter-operate with their legacy Id formats.
It is a tracestate in the [w3c-trace-context format](https://www.w3.org/TR/trace-context/#tracestate-header).
See also [https://github.com/w3c/distributed-tracing](https://github.com/w3c/distributed-tracing)
for more details about this field.
"""
@type tracestate() :: :opentelemetry.tracestate()
@typedoc """
A Link is a pointer from the current span to another span in the same trace or in a
different trace. For example, this can be used in batching operations,
where a single batch handler processes multiple requests from different
traces or when the handler receives a request from a different project.
"""
@type link() :: :opentelemetry.link()
@typedoc """
An Event is a time-stamped annotation of the span, consisting of user-supplied
text description and key-value pairs.
"""
@type event() :: :opentelemetry.event()
@type event_name() :: :opentelemetry.event_name()
@typedoc """
An optional final status for this span. Semantically when Status
wasn't set it means span ended without errors and assume `:unset`.
Application developers may set the status as `:ok` when the operation
has been validated to have completed successfully, or `:error` when
the operation contains an error.
"""
@type status() :: :opentelemetry.status()
@type status_code() :: :opentelemetry.status_code()
defdelegate get_tracer(name), to: :opentelemetry
defdelegate get_tracer(name, vsn, schema_url), to: :opentelemetry
defdelegate set_default_tracer(t), to: :opentelemetry
# Helpers to build OpenTelemetry structured types
@doc """
A monotonically increasing time provided by the Erlang runtime system in the native time unit.
This value is the most accurate and precise timestamp available from the Erlang runtime and
should be used for finding durations or any timestamp that can be converted to a system
time before being sent to another system.
Use `convert_timestamp/2` or `timestamp_to_nano/1` to convert a native monotonic time to a
system time of either nanoseconds or another unit.
Using these functions allows timestamps to be accurate, used for duration and be exportable
as POSIX time when needed.
"""
@spec timestamp() :: integer()
defdelegate timestamp(), to: :opentelemetry
@doc """
Convert a native monotonic timestamp to nanosecond POSIX time. Meaning the time since Epoch.
Epoch is defined to be 00:00:00 UTC, 1970-01-01.
"""
@spec timestamp_to_nano(integer()) :: integer()
defdelegate timestamp_to_nano(timestamp), to: :opentelemetry
@doc """
Convert a native monotonic timestamp to POSIX time of any `t::erlang.time_unit/0`.
Meaning the time since Epoch. Epoch is defined to be 00:00:00 UTC, 1970-01-01.
"""
@spec convert_timestamp(integer(), :erlang.time_unit()) :: integer()
defdelegate convert_timestamp(timestamp, unit), to: :opentelemetry
# span item functions
@doc """
Creates a `t:link/0`.
"""
@spec link(trace_id(), span_id(), attributes_map(), tracestate()) :: link()
defdelegate link(trace_id, span_id, attributes, tracestate), to: :opentelemetry
@doc """
Creates a `t:link/0` from a `t:span_ctx/0`.
"""
@spec link(span_ctx() | :undefined) :: link()
defdelegate link(span_ctx), to: :opentelemetry
@doc """
Creates a `t:link/0` from a `t:span_ctx/0` and list of `t:attributes_map/0`.
"""
@spec link(span_ctx() | :undefined, attributes_map()) :: link()
defdelegate link(span_ctx, attributes), to: :opentelemetry
@doc """
Creates a list of `t:link/0` from a list of 4-tuples.
"""
@spec links([
{integer(), integer(), attributes_map(), tracestate()}
| span_ctx()
| {span_ctx(), attributes_map()}
]) :: [link()]
defdelegate links(link_list), to: :opentelemetry
@doc """
Creates a `t:event/0`.
"""
@spec event(event_name(), attributes_map()) :: event()
defdelegate event(name, attributes), to: :opentelemetry
@doc """
Creates a `t:event/0`.
"""
@spec event(integer(), event_name(), attributes_map()) :: event()
defdelegate event(timestamp, name, attributes), to: :opentelemetry
@doc """
Creates a list of `t:event/0` items.
"""
@spec events(list()) :: [event()]
defdelegate events(event_list), to: :opentelemetry
@doc """
Creates a Status with an empty description.
"""
@spec status(:opentelemetry.status_code()) :: status()
defdelegate status(code), to: :opentelemetry
@doc """
Creates a Status.
"""
@spec status(:opentelemetry.status_code(), String.t()) :: status()
defdelegate status(code, message), to: :opentelemetry
end

View File

@ -0,0 +1,16 @@
defmodule OpenTelemetry.Baggage do
@moduledoc """
Baggage is used to annotate telemetry, adding context and information to
metrics, traces, and logs. It is represented by a set of name/value pairs
describing user-defined properties.
"""
defdelegate set(keyvalues), to: :otel_baggage
defdelegate set(ctx_or_key, keyvalues), to: :otel_baggage
defdelegate set(ctx, key, value), to: :otel_baggage
defdelegate set(ctx, key, values, metadata), to: :otel_baggage
defdelegate get_all(), to: :otel_baggage
defdelegate get_all(ctx), to: :otel_baggage
defdelegate clear(), to: :otel_baggage
defdelegate clear(ctx), to: :otel_baggage
end

View File

@ -0,0 +1,20 @@
defmodule OpenTelemetry.Ctx do
@moduledoc """
Ctx is responsible for propagating values within a process that are associated
with a particular Trace or set of Baggage. `OpenTelemetry.Tracer` and
`OpenTelemetry.Baggage` handle updating the Context.
"""
@type t() :: :otel_ctx.t()
defdelegate new(), to: :otel_ctx
defdelegate attach(ctx), to: :otel_ctx
defdelegate detach(token), to: :otel_ctx
defdelegate set_value(key, value), to: :otel_ctx
defdelegate set_value(ctx, key, value), to: :otel_ctx
defdelegate get_value(key, default), to: :otel_ctx
defdelegate get_value(ctx, key, default), to: :otel_ctx
defdelegate clear(), to: :otel_ctx
defdelegate remove(key), to: :otel_ctx
defdelegate get_current(), to: :otel_ctx
end

View File

@ -0,0 +1,212 @@
defmodule OpenTelemetry.Span do
@moduledoc """
This module contains macros for Span operations that update the active current Span in the current process.
An example of creating an Event and adding it to the current Span:
require OpenTelemetry.Tracer, as: Tracer
require OpenTelemetry.Span, as: Span
span_ctx = Tracer.start_span("some-span")
...
Span.add_event(span_ctx, "ecto.query", query: query, total_time: total_time)
...
Span.end_span(span_ctx)
A Span represents a single operation within a trace. Spans can be nested to form a trace tree.
Each trace contains a root span, which typically describes the end-to-end latency and, optionally,
one or more sub-spans for its sub-operations.
Spans encapsulate:
- The span name
- An immutable SpanContext (`t:OpenTelemetry.span_ctx/0`) that uniquely identifies the Span
- A parent Span in the form of a Span (`t:OpenTelemetry.span/0`), SpanContext (`t:OpenTelemetry.span_ctx/0`), or `undefined`
- A start timestamp
- An end timestamp
- An ordered mapping of Attributes (`t:OpenTelemetry.attributes_map/0`)
- A list of Links to other Spans (`t:OpenTelemetry.link/0`)
- A list of timestamped Events (`t:OpenTelemetry.event/0`)
- A Status (`t:OpenTelemetry.status/0`)
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#span)
"""
@type start_opts() :: :otel_span.start_opts()
@type start_config() :: :otel_span.start_config()
@doc """
Get the SpanId of a Span.
"""
@spec span_id(OpenTelemetry.span_ctx()) :: OpenTelemetry.span_id()
defdelegate span_id(span), to: :otel_span
@doc """
Get the hex-encoded trace context.
"""
@spec hex_span_ctx(OpenTelemetry.span_ctx() | nil) ::
%{
otel_trace_id: OpenTelemetry.hex_trace_id(),
otel_span_id: OpenTelemetry.hex_span_id(),
otel_trace_flags: binary()
}
| %{}
defdelegate hex_span_ctx(span_ctx), to: :otel_span
@doc """
Get the lowercase hex encoded span ID.
"""
@spec hex_span_id(OpenTelemetry.span_ctx()) :: OpenTelemetry.hex_span_id()
defdelegate hex_span_id(span), to: :otel_span
@doc """
Get the TraceId of a Span.
"""
@spec trace_id(OpenTelemetry.span_ctx()) :: OpenTelemetry.trace_id()
defdelegate trace_id(span), to: :otel_span
@doc """
Get the lowercase hex encoded trace ID.
"""
@spec hex_trace_id(OpenTelemetry.span_ctx()) :: OpenTelemetry.hex_trace_id()
defdelegate hex_trace_id(span), to: :otel_span
@doc """
Get the Tracestate of a Span.
"""
@spec tracestate(OpenTelemetry.span_ctx()) :: OpenTelemetry.tracestate()
defdelegate tracestate(span), to: :otel_span
@doc """
End the Span. Sets the end timestamp for the currently active Span. This has no effect on any
child Spans that may exist of this Span.
The Span Context is returned with `is_recording` set to `false`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#end)
"""
defdelegate end_span(span_ctx), to: :otel_span
@doc """
End the Span. Sets the end timestamp for the currently active Span using the passed in timestamp if valid, current timestamp otherwise. This has no effect on any
child Spans that may exist of this Span.
The Span Context is returned with `is_recording` set to `false`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#end)
"""
defdelegate end_span(span_ctx, timestamp), to: :otel_span
@doc """
Returns whether this Span is recording information like events, attributes, status, etc.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#isrecording)
"""
defdelegate is_recording(span_ctx), to: :otel_span
@doc """
Returns true if the SpanContext has a non-zero TraceId and SpanId.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#isvalid)
"""
defdelegate is_valid(span_ctx), to: :otel_span
@doc """
Set an attribute with key and value on the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-attributes)
"""
@spec set_attribute(
OpenTelemetry.span_ctx(),
OpenTelemetry.attribute_key(),
OpenTelemetry.attribute_value()
) :: boolean()
defdelegate set_attribute(span_ctx, key, value), to: :otel_span
@doc """
Add a list of attributes to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-attributes)
"""
@spec set_attributes(OpenTelemetry.span_ctx(), OpenTelemetry.attributes_map()) :: boolean()
defdelegate set_attributes(span_ctx, attributes), to: :otel_span
@doc """
Add an event to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#add-events)
"""
@spec add_event(
OpenTelemetry.span_ctx(),
OpenTelemetry.event_name(),
OpenTelemetry.attributes_map()
) :: boolean()
defdelegate add_event(span_ctx, event, attributes), to: :otel_span
@doc """
Add a list of events to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#add-events)
"""
@spec add_events(OpenTelemetry.span_ctx(), [OpenTelemetry.event()]) :: boolean()
defdelegate add_events(span_ctx, events), to: :otel_span
defguardp is_exception?(term)
when is_map(term) and :erlang.is_map_key(:__struct__, term) and
is_atom(:erlang.map_get(:__struct__, term)) and
:erlang.is_map_key(:__exception__, term) and
:erlang.map_get(:__exception__, term) == true
@doc """
Record an exception as an event, following the semantics convetions for exceptions.
If trace is not provided, the stacktrace is retrieved from `Process.info/2`
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#record-exception)
"""
@spec record_exception(OpenTelemetry.span_ctx(), Exception.t()) :: boolean()
def record_exception(span_ctx, exception, trace \\ nil, attributes \\ [])
def record_exception(span_ctx, exception, trace, attributes) when is_exception?(exception) do
exception_type = to_string(exception.__struct__)
exception_attributes = [
{:"exception.type", exception_type},
{:"exception.message", Exception.message(exception)},
{:"exception.stacktrace", Exception.format_stacktrace(trace)}
]
add_event(span_ctx, :exception, exception_attributes ++ attributes)
end
def record_exception(_, _, _, _), do: false
@doc """
Sets the Status of the currently active Span.
If used, this will override the default Span Status, which is `:unset`.
Valid statuses are `:ok`, or `:error`. Calling this will also set the
`status_code` attribute to `1`(`:ok`), or `2`(`:error`).
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-status)
"""
@spec set_status(OpenTelemetry.span_ctx(), OpenTelemetry.status()) :: boolean()
defdelegate set_status(span_ctx, status), to: :otel_span
@doc """
Updates the Span name.
It is highly discouraged to update the name of a Span after its creation. Span name is
often used to group, filter and identify the logical groups of spans. And often, filtering
logic will be implemented before the Span creation for performance reasons. Thus the name
update may interfere with this logic.
The function name is called update_name to differentiate this function from the regular
property setter. It emphasizes that this operation signifies a major change for a Span
and may lead to re-calculation of sampling or filtering decisions made previously
depending on the implementation.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#updatename)
"""
@spec update_name(OpenTelemetry.span_ctx(), OpenTelemetry.span_name()) :: boolean()
defdelegate update_name(span_ctx, name), to: :otel_span
end

View File

@ -0,0 +1,260 @@
defmodule OpenTelemetry.Tracer do
@moduledoc """
This module contains macros for Tracer operations around the lifecycle of the Spans within a Trace.
The Tracer is able to start a new Span as a child of the active Span of the current process, set
a different Span to be the current Span by passing the Span's context, end a Span or run a code
block within the context of a newly started span that is ended when the code block completes.
The macros `start_span` and `with_span` use the Tracer associated with the Application the module
is included in. These Tracers are created at boot time for each loaded Application.
require OpenTelemetry.Tracer, as: Tracer
Tracer.with_span "span-1" do
... do something ...
end
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#tracer)
"""
@doc """
Starts a new span and does not make it the current active span of the current process.
The current active Span is used as the parent of the created Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#span-creation)
"""
defmacro start_span(name, opts \\ quote(do: %{})) do
quote bind_quoted: [name: name, start_opts: opts] do
:otel_tracer.start_span(
:opentelemetry.get_application_tracer(__MODULE__),
name,
Map.new(start_opts)
)
end
end
@doc """
Starts a new span and does not make it the current active span of the current process.
The current active Span is used as the parent of the created Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#span-creation)
"""
defmacro start_span(ctx, name, opts) do
quote bind_quoted: [ctx: ctx, name: name, start_opts: opts] do
:otel_tracer.start_span(
ctx,
:opentelemetry.get_application_tracer(__MODULE__),
name,
Map.new(start_opts)
)
end
end
@doc """
Takes a `t:OpenTelemetry.span_ctx/0` and the Tracer sets it to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#get-context)
"""
def set_current_span(span_ctx) do
:otel_tracer.set_current_span(span_ctx)
end
@doc """
Takes a `t:OpenTelemetry.Ctx.t/0` and the `t:OpenTelemetry.span_ctx/0` and the Tracer sets
it to the current span in the pass Context.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#get-context)
"""
def set_current_span(ctx, span_ctx) do
:otel_tracer.set_current_span(ctx, span_ctx)
end
@doc """
Creates a new span which is set to the currently active Span in the Context of the block.
The Span is ended automatically when the `block` completes and the Context is what it was
before the block.
See `start_span/2` and `end_span/0`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#span-creation)
"""
defmacro with_span(name, start_opts \\ quote(do: %{}), do: block) do
quote do
:otel_tracer.with_span(
:opentelemetry.get_application_tracer(__MODULE__),
unquote(name),
Map.new(unquote(start_opts)),
fn _ -> unquote(block) end
)
end
end
@doc """
Creates a new span which is set to the currently active Span in the Context of the block.
The Span is ended automatically when the `block` completes and the Context is what it was
before the block.
See `start_span/2` and `end_span/0`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#span-creation)
"""
defmacro with_span(ctx, name, start_opts, do: block) do
quote do
:otel_tracer.with_span(
unquote(ctx),
:opentelemetry.get_application_tracer(__MODULE__),
unquote(name),
Map.new(unquote(start_opts)),
fn _ -> unquote(block) end
)
end
end
@doc """
Returns the currently active `t:OpenTelemetry.span_ctx/0`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#get-context)
"""
def current_span_ctx() do
:otel_tracer.current_span_ctx()
end
@doc """
Returns the `t:OpenTelemetry.span_ctx/0` active in Context `ctx`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#get-context)
"""
def current_span_ctx(ctx) do
:otel_tracer.current_span_ctx(ctx)
end
@doc """
End the currently active Span and sets its end timestamp.
This has no effect on any child Spans that may exist of this Span.
To end a specific span, see `OpenTelemetry.Span.end_span/1`.
The Span in the current Context has its `is_recording` set to `false`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#end)
"""
@spec end_span(:opentelemetry.timestamp() | :undefined) ::
:opentelemetry.span_ctx() | :undefined
def end_span(timestamp \\ :undefined) do
non_recording_span = :otel_span.end_span(:otel_tracer.current_span_ctx(), timestamp)
_ = :otel_tracer.set_current_span(non_recording_span)
non_recording_span
end
@doc """
Set an attribute with key and value on the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-attributes)
"""
@spec set_attribute(OpenTelemetry.attribute_key(), OpenTelemetry.attribute_value()) :: boolean()
def set_attribute(key, value) do
:otel_span.set_attribute(
:otel_tracer.current_span_ctx(),
key,
value
)
end
@doc """
Add a list of attributes to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-attributes)
"""
@spec set_attributes(OpenTelemetry.attributes_map()) :: boolean()
def set_attributes(attributes) do
:otel_span.set_attributes(:otel_tracer.current_span_ctx(), attributes)
end
@doc """
Add an event to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#add-events)
"""
@spec add_event(OpenTelemetry.event_name(), OpenTelemetry.attributes_map()) :: boolean()
def add_event(event, attributes) do
:otel_span.add_event(
:otel_tracer.current_span_ctx(),
event,
attributes
)
end
@doc """
Add a list of events to the currently active Span.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#add-events)
"""
@spec add_events([OpenTelemetry.event()]) :: boolean()
def add_events(events) do
:otel_span.add_events(:otel_tracer.current_span_ctx(), events)
end
@doc """
Record an exception as an event, following the semantics convetions for exceptions.
If trace is not provided, the stacktrace is retrieved from `Process.info/2`
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#record-exception)
"""
@spec record_exception(Exception.t()) :: boolean()
def record_exception(exception, trace \\ nil, attributes \\ []) do
OpenTelemetry.Span.record_exception(
:otel_tracer.current_span_ctx(),
exception,
trace,
attributes
)
end
@doc """
Creates and sets the Status of the currently active Span.
If used, this will override the default Span Status, which is `:unset`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-status)
"""
@spec set_status(OpenTelemetry.status_code(), String.t()) :: boolean()
def set_status(code, message) do
:otel_span.set_status(:otel_tracer.current_span_ctx(), code, message)
end
@doc """
Sets the Status of the currently active Span.
If used, this will override the default Span Status, which is `:unset`.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#set-status)
"""
@spec set_status(OpenTelemetry.status()) :: boolean()
def set_status(status) do
:otel_span.set_status(:otel_tracer.current_span_ctx(), status)
end
@doc """
Updates the Span name.
It is highly discouraged to update the name of a Span after its creation. Span name is
often used to group, filter and identify the logical groups of spans. And often, filtering
logic will be implemented before the Span creation for performance reasons. Thus the name
update may interfere with this logic.
The function name is called update_name to differentiate this function from the regular
property setter. It emphasizes that this operation signifies a major change for a Span
and may lead to re-calculation of sampling or filtering decisions made previously
depending on the implementation.
See [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/trace/api.md#updatename)
"""
@spec update_name(String.t()) :: boolean()
def update_name(name) do
:otel_span.update_name(:otel_tracer.current_span_ctx(), name)
end
end

View File

@ -0,0 +1,87 @@
defmodule OpenTelemetry.MixProject do
use Mix.Project
def project do
{app, desc} = load_app()
[
app: app,
version: to_string(Keyword.fetch!(desc, :vsn)),
description: to_string(Keyword.fetch!(desc, :description)),
elixir: "~> 1.8",
start_permanent: Mix.env() == :prod,
deps: [
{:eqwalizer_support,
git: "https://github.com/whatsapp/eqwalizer.git",
branch: "main",
sparse: "eqwalizer_support",
only: [:dev],
runtime: false},
{:dialyxir, "~> 1.0", only: [:dev], runtime: false},
{:covertool, ">= 0.0.0", only: :test},
{:ex_doc, "~> 0.37", only: :dev, runtime: false}
],
name: "OpenTelemetry API",
test_coverage: [tool: :covertool],
package: package(),
dialyzer: [
ignore_warnings: "dialyzer.ignore-warnings",
remove_defaults: [:unknown],
plt_add_apps: [:eqwalizer_support],
list_unused_filters: true
],
source_url: "https://github.com/open-telemetry/opentelemetry-erlang",
homepage_url: "https://github.com/open-telemetry/opentelemetry-erlang",
docs: [
main: "readme",
source_url_pattern:
"https://github.com/open-telemetry/opentelemetry-erlang/blob/main/apps/opentelemetry_api/%{path}#L%{line}",
extras: ["README.md", "LICENSE"],
groups_for_modules: [
Context: [:otel_ctx, OpenTelemetry.Ctx],
Baggage: [:otel_baggage, OpenTelemetry.Baggage],
Tracer: [
:otel_tracer,
:otel_tracer_noop,
:otel_tracer_provider,
:otel_tracestate,
OpenTelemetry.Tracer,
OpenTelemetry.Span
],
Propagators: [
:otel_propagator,
:otel_propagator_baggage,
:otel_propagator_b3,
:otel_propagator_b3multi,
:otel_propagator_b3single,
:otel_propagator_text_map,
:otel_propagator_text_map_composite,
:otel_propagator_text_map_noop,
:otel_propagator_trace_context
]
]
]
]
end
def application, do: []
defp package() do
[
description: "OpenTelemetry API",
build_tools: ["rebar3", "mix"],
files: ~w(lib mix.exs README.md LICENSE rebar.config include src),
licenses: ["Apache-2.0"],
links: %{
"GitHub" => "https://github.com/open-telemetry/opentelemetry-erlang",
"OpenTelemetry.io" => "https://opentelemetry.io"
}
]
end
defp load_app do
{:ok, [{:application, name, desc}]} = :file.consult(~c"src/opentelemetry_api.app.src")
{name, desc}
end
end

View File

@ -0,0 +1,12 @@
%{
"covertool": {:hex, :covertool, "2.0.6", "4a291b4e3449025b0595d8f44c8d7635d4f48f033be2ce88d22a329f36f94a91", [:rebar3], [], "hexpm", "5db3fcd82180d8ea4ad857d4d1ab21a8d31b5aee0d60d2f6c0f9e25a411d1e21"},
"dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"},
"earmark_parser": {:hex, :earmark_parser, "1.4.43", "34b2f401fe473080e39ff2b90feb8ddfeef7639f8ee0bbf71bb41911831d77c5", [:mix], [], "hexpm", "970a3cd19503f5e8e527a190662be2cee5d98eed1ff72ed9b3d1a3d466692de8"},
"eqwalizer_support": {:git, "https://github.com/whatsapp/eqwalizer.git", "1a787cb604f6083ebe8763e358ea362e4677e500", [branch: "main", sparse: "eqwalizer_support"]},
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
"ex_doc": {:hex, :ex_doc, "0.37.1", "65ca30d242082b95aa852b3b73c9d9914279fff56db5dc7b3859be5504417980", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "6774f75477733ea88ce861476db031f9399c110640752ca2b400dbbb50491224"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
}

View File

@ -0,0 +1,11 @@
{erl_opts, [debug_info]}.
{deps, []}.
{profiles,
[{docs, [{edoc_opts,
[
{doclet, edoc_doclet_chunks},
{layout, edoc_layout_chunks},
{preprocess, true},
{dir, "_build/dev/lib/opentelemetry_api/doc"},
{subpackages, true}]}]}]}.

View File

@ -0,0 +1,573 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc The types defined here, and referencing records in opentelemetry.hrl
%% are used to store trace information while being collected on the
%% Erlang node.
%%
%% Thus, while the types are based on protos found in the opentelemetry-proto
%% repo: src/opentelemetry/proto/trace/v1/trace.proto,
%% they are not exact translations because further processing is done after
%% the span has finished and can be vendor specific. For example, there is
%% no count of the number of dropped attributes in the span record. And
%% an attribute's value can be a function to only evaluate the value if it
%% is actually used (at the time of exporting). And the stacktrace is a
%% regular Erlang stack trace.
%% @end
%%%-------------------------------------------------------------------------
-module(opentelemetry).
-export([start_tracer_provider/2,
set_default_tracer/1,
set_default_tracer/2,
create_application_tracers/1,
get_tracer/0,
get_tracer/1,
get_tracer/3,
set_tracer/2,
get_application/1,
get_application_tracer/1,
get_application_scope/1,
set_text_map_propagator/1,
set_text_map_extractor/1,
get_text_map_extractor/0,
set_text_map_injector/1,
get_text_map_injector/0,
instrumentation_scope/3,
instrumentation_library/3,
timestamp/0,
timestamp_to_nano/1,
convert_timestamp/2,
link/1,
link/2,
link/4,
links/1,
event/2,
event/3,
events/1,
status/1,
status/2,
verify_and_set_term/3,
vsn_to_binary/1]).
-include("opentelemetry.hrl").
-include_lib("kernel/include/logger.hrl").
-export_type([tracer/0,
instrumentation_scope/0,
trace_id/0,
span_id/0,
hex_trace_id/0,
hex_span_id/0,
trace_flags/0,
timestamp/0,
span_name/0,
span_ctx/0,
span/0,
span_kind/0,
link/0,
attribute_key/0,
attribute_value/0,
attribute/0,
attributes_map/0,
event/0,
event_name/0,
tracestate/0,
status/0,
status_code/0,
resource/0,
text_map/0]).
-type tracer() :: {module(), term()}.
-type instrumentation_scope() :: #instrumentation_scope{}.
-type trace_id() :: non_neg_integer().
-type span_id() :: non_neg_integer().
-type hex_trace_id() :: binary().
-type hex_span_id() :: binary().
-type trace_flags() :: non_neg_integer().
-type timestamp() :: integer().
-type span_ctx() :: #span_ctx{}.
-type span() :: term().
-type span_name() :: unicode:unicode_binary() | atom().
-type attribute_key() :: unicode:unicode_binary() | atom().
-type attribute_value() :: unicode:unicode_binary() |
atom() |
number() |
boolean() |
[unicode:unicode_binary() | atom() | float() | integer() | boolean()] |
tuple().
-type attribute() :: {attribute_key(), attribute_value()}.
-type attributes_map() :: #{attribute_key() => attribute_value()} |
[attribute()].
-type span_kind() :: ?SPAN_KIND_INTERNAL |
?SPAN_KIND_SERVER |
?SPAN_KIND_CLIENT |
?SPAN_KIND_PRODUCER |
?SPAN_KIND_CONSUMER.
-type event() :: #{system_time_native => integer(),
name := event_name(),
attributes := attributes_map()}.
-type event_name() :: unicode:unicode_binary() | atom().
-type link() :: #{trace_id := trace_id(),
span_id := span_id(),
attributes := attributes_map(),
tracestate := otel_tracestate:t()}.
-type status() :: #status{}.
-type status_code() :: ?OTEL_STATUS_UNSET | ?OTEL_STATUS_OK | ?OTEL_STATUS_ERROR.
%% The key must begin with a lowercase letter, and can only contain
%% lowercase letters 'a'-'z', digits '0'-'9', underscores '_', dashes
%% '-', asterisks '*', and forward slashes '/'.
%% The value is opaque string up to 256 characters printable ASCII
%% RFC0020 characters (i.e., the range 0x20 to 0x7E) except ',' and '='.
%% Note that this also excludes tabs, newlines, carriage returns, etc.
-type tracestate() :: otel_tracestate:t().
-type resource() :: #{unicode:unicode_binary() => unicode:unicode_binary()}.
-type text_map() :: [{unicode:unicode_binary(), unicode:unicode_binary()}].
-define(TRACER_KEY(TracerProvider, Name), {?MODULE, TracerProvider, tracer, Name}).
-define(DEFAULT_TRACER_KEY(TracerProvider), ?TRACER_KEY(TracerProvider, '$__default_tracer')).
-define(MODULE_TO_APPLICATION_KEY, {?MODULE, otel_module_to_application_key}).
-define(TEXT_MAP_EXTRACTOR_KEY, {?MODULE, text_map_extractor}).
-define(TEXT_MAP_INJECTOR_KEY, {?MODULE, text_map_injector}).
%% uncomment when OTP-23 becomes the minimum required version
%% -deprecated({start_tracer_provider, 2, "start the TracerProvider through the SDK"}).
-include("gradualizer.hrl").
%% @deprecated Start the TracerProvider through the SDK"
-spec start_tracer_provider(atom(), map()) -> {ok, pid() | undefined} | {error, term()}.
start_tracer_provider(Name, Config) ->
otel_tracer_provider:start(Name, Config).
-spec set_default_tracer(tracer()) -> boolean().
set_default_tracer(Tracer) ->
set_default_tracer(?GLOBAL_TRACER_PROVIDER_NAME, Tracer).
-spec set_default_tracer(atom(), tracer()) -> boolean().
set_default_tracer(TracerProvider, Tracer) ->
verify_and_set_term(Tracer, ?DEFAULT_TRACER_KEY(TracerProvider), otel_tracer).
-spec set_tracer(atom(), tracer()) -> boolean().
set_tracer(Name, Tracer) ->
set_tracer(Name, <<>>, undefined, Tracer).
-spec set_tracer(Name, Vsn, SchemaUrl, Tracer) -> boolean() when
Name :: atom(),
Vsn :: unicode:chardata() | undefined,
SchemaUrl :: uri_string:uri_string() | undefined,
Tracer:: opentelemetry:tracer().
set_tracer(Name, Vsn, SchemaUrl, Tracer) ->
set_tracer(?GLOBAL_TRACER_PROVIDER_NAME, Name, Vsn, SchemaUrl, Tracer).
-spec set_tracer(TracerProvider, Name, Vsn, SchemaUrl, Tracer) -> boolean() when
TracerProvider :: atom(),
Name :: atom(),
Vsn :: unicode:chardata() | undefined,
SchemaUrl :: uri_string:uri_string() | undefined,
Tracer:: opentelemetry:tracer().
set_tracer(TracerProvider, Name, Vsn, SchemaUrl, Tracer) ->
verify_and_set_term(Tracer, ?TRACER_KEY(TracerProvider, {Name, Vsn, SchemaUrl}), otel_tracer).
-spec create_application_tracers([{Application, Description, Vsn}]) -> ok when
Application :: atom(),
Description :: string(),
Vsn :: string().
create_application_tracers(Applications) ->
TracerMap = lists:foldl(fun({Name, _Description, Version}, Acc) ->
Vsn = vsn_to_binary(Version),
SchemaUrl = application:get_env(Name, otel_schema_url, undefined),
_ = get_tracer(Name, Version, SchemaUrl),
maps:merge(Acc, module_to_application(Name, Vsn, SchemaUrl))
end, #{}, Applications),
persistent_term:put(?MODULE_TO_APPLICATION_KEY, TracerMap).
%% creates a map of modules to application name, version and schema_url tuple
module_to_application(Name, Version, SchemaUrl) ->
{ok, Modules} = application:get_key(Name, modules),
lists:foldl(fun(M, Acc) ->
Acc#{M => {Name, Version, SchemaUrl}}
end, #{}, Modules).
%% @doc Returns the default global tracer.
%%
%% Without the `opentelemetry' application loaded (as a dependency) and
%% started (or another SDK), this function returns the default value
%% `{otel_tracer_noop, []}'.
-spec get_tracer() -> tracer().
get_tracer() ->
get_tracer_(?GLOBAL_TRACER_PROVIDER_NAME).
-spec get_tracer_(atom()) -> tracer().
get_tracer_(TracerProvider) ->
persistent_term:get(?DEFAULT_TRACER_KEY(TracerProvider), {otel_tracer_noop, []}).
%% @doc Returns the tracer for the given name.
%%
%% Passing `{Name, Vsn, SchemaUrl}' is the same as calling
%% `get_tracer(Name, Vsn, SchemaUrl)'.
%% @see get_tracer/3
-spec get_tracer(Name) -> Tracer when
Name :: atom() | {atom(), Vsn, SchemaUrl},
Vsn :: unicode:chardata() | undefined,
SchemaUrl :: uri_string:uri_string() | undefined,
Tracer :: opentelemetry:tracer().
get_tracer('$__default_tracer') ->
get_tracer();
get_tracer({Name, Vsn, SchemaUrl}) ->
get_tracer(Name, Vsn, SchemaUrl);
get_tracer(Name) ->
get_tracer(Name, undefined, undefined).
%% @equiv get_tracer({Name, Vsn, SchemaUrl})
-spec get_tracer(Name, Vsn, SchemaUrl) -> Tracer when
Name :: atom(),
Vsn :: unicode:chardata() | undefined,
SchemaUrl :: uri_string:uri_string() | undefined,
Tracer :: opentelemetry:tracer().
get_tracer(Name, Vsn, SchemaUrl) ->
get_tracer(?GLOBAL_TRACER_PROVIDER_NAME, Name, Vsn, SchemaUrl).
-spec get_tracer(TracerProvider, Name, Vsn, SchemaUrl) -> Tracer when
TracerProvider :: atom() | pid(),
Name :: atom(),
Vsn :: unicode:chardata() | undefined,
SchemaUrl :: uri_string:uri_string() | undefined,
Tracer :: opentelemetry:tracer().
get_tracer(TracerProvider, Name, Vsn, SchemaUrl) ->
%% check cache and then use provider to get the tracer if it isn't cached yet
case persistent_term:get(?TRACER_KEY(TracerProvider, {Name, Vsn, SchemaUrl}), undefined) of
undefined ->
VsnBin = vsn_to_binary(Vsn),
Tracer = otel_tracer_provider:get_tracer(TracerProvider, Name, VsnBin, SchemaUrl),
%% cache the tracer
_ = set_tracer(Name, Vsn, SchemaUrl, Tracer),
Tracer;
Tracer ->
Tracer
end.
-spec get_application_tracer(module()) -> tracer().
get_application_tracer(ModuleName) ->
get_tracer(get_application(ModuleName)).
-spec get_application_scope(module()) -> instrumentation_scope() | undefined.
get_application_scope(ModuleName) ->
case get_application(ModuleName) of
{Name, Vsn, SchemaUrl} ->
instrumentation_scope(Name, Vsn, SchemaUrl);
_ ->
instrumentation_scope(<<>>, <<>>, <<>>)
end.
%% looks up the name, version and schema_url used to create a Trace for the OTP
%% Application a module is in. This name is used to look up a Tracer to use so
%% if none is found for the ModuleName the key used for the default tracer.
-spec get_application(module()) -> ApplicationTuple when
ApplicationTuple :: {Name, Vsn, SchemaUrl} | atom(),
Name :: atom(),
Vsn :: unicode:unicode_binary() | undefined,
SchemaUrl :: uri_string:uri_string() | undefined.
get_application(ModuleName) ->
Map = persistent_term:get(?MODULE_TO_APPLICATION_KEY, #{}),
maps:get(ModuleName, Map, '$__default_tracer').
%% setting the propagator is the same as setting the same injector and extractor
set_text_map_propagator(Propagator) ->
set_text_map_injector(Propagator),
set_text_map_extractor(Propagator).
set_text_map_extractor(Propagator) ->
persistent_term:put(?TEXT_MAP_EXTRACTOR_KEY, Propagator).
set_text_map_injector(Propagator) ->
persistent_term:put(?TEXT_MAP_INJECTOR_KEY, Propagator).
get_text_map_extractor() ->
persistent_term:get(?TEXT_MAP_EXTRACTOR_KEY, otel_propagator_text_map_noop).
get_text_map_injector() ->
persistent_term:get(?TEXT_MAP_INJECTOR_KEY, otel_propagator_text_map_noop).
%% @doc A monotonically increasing time provided by the Erlang runtime system in the native time unit.
%% This value is the most accurate and precise timestamp available from the Erlang runtime and
%% should be used for finding durations or any timestamp that can be converted to a system
%% time before being sent to another system.
%% Use {@link convert_timestamp/2} or {@link timestamp_to_nano/1} to convert a native monotonic time to a
%% system time of either nanoseconds or another {@link erlang:time_unit()}.
%% Using these functions allows timestamps to be accurate, used for duration and be exportable
%% as POSIX time when needed.
%% @end
-spec timestamp() -> integer().
timestamp() ->
erlang:monotonic_time().
%% @doc Convert a native monotonic timestamp to nanosecond POSIX time. Meaning the time since Epoch.
%% Epoch is defined to be 00:00:00 UTC, 1970-01-01.
%% @end
-spec timestamp_to_nano(timestamp()) -> pos_integer().
timestamp_to_nano(Timestamp) ->
?assert_type(convert_timestamp(Timestamp, nanosecond), pos_integer()).
%% @doc Convert a native monotonic timestamp to POSIX time of any {@link erlang:time_unit()}.
%% Meaning the time since Epoch. Epoch is defined to be 00:00:00 UTC, 1970-01-01.
%% @end
-spec convert_timestamp(timestamp(), erlang:time_unit()) -> integer().
convert_timestamp(Timestamp, Unit) ->
Offset = erlang:time_offset(),
erlang:convert_time_unit(Timestamp + Offset, native, Unit).
%% @doc Creates a list of Span links from the given `List'.
%%
%% This is equivalent to calling {@link link/2} or {@link link/4} multiple times.
-spec links([TraceIdAndSpanId | span_ctx() | {span_ctx(), Attributes}]) -> [link()] when
TraceIdAndSpanId :: {trace_id(), span_id(), Attributes, TraceState},
Attributes :: attributes_map(),
TraceState :: otel_tracestate:t() | [{string(), string()}].
links(List) when is_list(List) ->
lists:filtermap(fun({TraceId, SpanId, Attributes, TraceState}) when is_integer(TraceId) ,
is_integer(SpanId) ->
link_or_false(TraceId, SpanId, otel_attributes:process_attributes(Attributes), TraceState);
({#span_ctx{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState}, Attributes}) when is_integer(TraceId) ,
is_integer(SpanId) ->
link_or_false(TraceId, SpanId, otel_attributes:process_attributes(Attributes), TraceState);
(#span_ctx{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState}) when is_integer(TraceId) ,
is_integer(SpanId) ->
link_or_false(TraceId, SpanId, [], TraceState);
(_) ->
false
end, List);
links(_) ->
[].
%% @equiv link(SpanCtx, [])
-spec link(span_ctx() | undefined) -> link() | undefined.
link(SpanCtx) ->
link(SpanCtx, []).
%% @doc Creates a Span link to the Span represented by the given `SpanCtx'.
%%
%% The returned link can be used in the `links' field of a Span.
-spec link(span_ctx() | undefined, attributes_map()) -> link() | undefined.
link(_SpanCtx = #span_ctx{trace_id=TraceId,
span_id=SpanId,
tracestate=TraceState}, Attributes) ->
?MODULE:link(TraceId, SpanId, otel_attributes:process_attributes(Attributes), TraceState);
link(_, _) ->
undefined.
%% @doc Creates a Span link to the Span represented by the given `TraceId' and `SpanId'.
%%
%% The returned link can be used in the `links' field of a Span.
-spec link(TraceId, SpanId, Attributes, TraceState) -> link() | undefined when
TraceId :: trace_id(),
SpanId :: span_id(),
Attributes :: attributes_map(),
TraceState :: otel_tracestate:t().
link(TraceId, SpanId, Attributes, TraceState) when is_integer(TraceId),
is_integer(SpanId),
(is_list(Attributes) orelse is_map(Attributes)) ->
#{trace_id => TraceId,
span_id => SpanId,
attributes => otel_attributes:process_attributes(Attributes),
tracestate => TraceState};
link(_, _, _, _) ->
undefined.
%% @equiv event(opentelemetry:timestamp(), Name, Attributes)
-spec event(Name, Attributes) -> event() | undefined when
Name :: event_name(),
Attributes :: attributes_map().
event(Name, Attributes) ->
event(opentelemetry:timestamp(), Name, Attributes).
%% @doc Creates a Span event with the given `Name' and `Attributes'.
%%
%% The Span event is marked to have happened at `Timestamp'. The returned
%% event can be used to add an event to a Span through {@link otel_span:add_events/2},
%% for example.
-spec event(Timestamp, Name, Attributes) -> event() | undefined when
Timestamp :: integer(),
Name :: event_name(),
Attributes :: attributes_map().
event(Timestamp, Name, Attributes) when is_integer(Timestamp),
(is_list(Attributes) orelse is_map(Attributes)) ->
case otel_span:is_valid_name(Name) of
true ->
#{system_time_native => Timestamp,
name => Name,
attributes => otel_attributes:process_attributes(Attributes)};
false ->
undefined
end;
event(_, _, _) ->
undefined.
%% @doc Creates a list of Span events from the given `List'.
%%
%% This is a convenience function to create a list of Span events from a list
%% of `{Time, Name, Attributes}' or `{Name, Attributes}' tuples. It's equivalent
%% to calling {@link event/2} or {@link event/3} multiple times. This function
%% also automatically filters out any invalid tuple.
-spec events([Event]) -> [event()] when
Event :: {Timestamp :: integer(), event_name(), attributes_map()} |
{event_name(), attributes_map()}.
events(Events) ->
Now = opentelemetry:timestamp(),
lists:filtermap(fun({Time, Name, Attributes}) ->
case event(Time, Name, Attributes) of
undefined ->
false;
Event ->
{true, Event}
end;
({Name, Attributes}) ->
case event(Now, Name, Attributes) of
undefined ->
false;
Event ->
{true, Event}
end;
(_) ->
false
end, Events).
%% @doc Create a Span status from the given `Code'.
%%
%% The returned status can be used to set the status of a Span through
%% {@link otel_span:set_status/2}, for example.
-spec status(Code) -> status() | undefined when
Code :: status_code().
status(Code) ->
status(Code, <<>>).
%% @doc Create a Span status from the given `Code' and with the given `Message'.
%%
%% The returned status can be used to set the status of a Span through
%% {@link otel_span:set_status/2}, for example.
-spec status(Code, Message) -> status() | undefined when
Code :: status_code(),
Message :: unicode:unicode_binary().
status(?OTEL_STATUS_ERROR, Message) when is_binary(Message) ->
#status{code=?OTEL_STATUS_ERROR, message=Message};
status(?OTEL_STATUS_OK, _Message) ->
#status{code=?OTEL_STATUS_OK};
status(?OTEL_STATUS_UNSET, _Message) ->
#status{code=?OTEL_STATUS_UNSET};
status(_, _) ->
undefined.
%% internal functions
%% @private
-spec verify_and_set_term(module() | {module(), term()}, term(), atom()) -> boolean().
verify_and_set_term(Module, TermKey, Behaviour) ->
case verify_module_exists(Module) of
true ->
persistent_term:put(TermKey, Module),
true;
false ->
?LOG_WARNING("Module ~p does not exist. "
"A noop ~p will be used.",
[Module, Behaviour]),
false
end.
%% @private
-spec verify_module_exists(module() | {module(), term()}) -> boolean().
verify_module_exists({Module, _}) ->
verify_module_exists(Module);
verify_module_exists(Module) ->
try Module:module_info() of
_ ->
true
catch
error:undef ->
false
end.
%% for use in a filtermap
%% return {true, Link} if a link is returned or return false
%% a list is supported for tracestate for backwards compatibility
%% @private
link_or_false(TraceId, SpanId, Attributes, TraceState) when is_list(TraceState) ->
link_or_false(TraceId, SpanId, Attributes, otel_tracestate:new(TraceState));
link_or_false(TraceId, SpanId, Attributes, TraceState) ->
case link(TraceId, SpanId, Attributes, TraceState) of
Link=#{}->
{true, Link};
_ ->
false
end.
instrumentation_scope(Name, Vsn, SchemaUrl) ->
case name_to_binary(Name) of
undefined ->
undefined;
BinaryName ->
#instrumentation_scope{name=BinaryName,
version=vsn_to_binary(Vsn),
schema_url=schema_url_to_binary(SchemaUrl)}
end.
%% this function remains solely to keep backwards compatibility
%% but `instrumentation_scope' should be used instead
instrumentation_library(Name, Vsn, SchemaUrl) ->
instrumentation_scope(Name, Vsn, SchemaUrl).
%% schema_url is option, so set to undefined if its not a string
schema_url_to_binary(SchemaUrl) when is_binary(SchemaUrl) ; is_list(SchemaUrl) ->
unicode:characters_to_binary(SchemaUrl);
schema_url_to_binary(_) ->
undefined.
%% Vsn can't be an atom or anything but a list or binary
%% so return empty binary string if it isn't a list or binary.
%% @private
vsn_to_binary(Vsn) when is_binary(Vsn) ; is_list(Vsn) ->
unicode:characters_to_binary(Vsn);
vsn_to_binary(_) ->
<<>>.
%% Instrumentation name can be atom, list or binary. But atom `undefined'
%% must stay as `undefined' atom.
name_to_binary(undefined)->
undefined;
name_to_binary(T) when is_atom(T) ->
atom_to_binary(T, utf8);
name_to_binary(T) when is_list(T) ->
list_to_binary(T);
name_to_binary(T) when is_binary(T) ->
T.

View File

@ -0,0 +1,15 @@
{application, opentelemetry_api,
[{description, "OpenTelemetry API"},
{vsn, "1.4.1"},
{registered, []},
{applications,
[kernel,
stdlib
]},
{exclude_paths, ["rebar.lock"]},
{env,[]},
{modules, []},
{licenses, ["Apache-2.0"]},
{links, [{"GitHub", "https://github.com/open-telemetry/opentelemetry-erlang"}]}
]}.

View File

@ -0,0 +1,219 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc Functions to work with Attributes.
%%
%% An Attribute is a key-value pair with string or atom keys.
%% See <a href="https://opentelemetry.io/docs/specs/otel/common/#attribute">the specification</a>.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_attributes).
-export([new/3,
set/2,
set/3,
dropped/1,
map/1,
is_valid_attribute/2,
process_attributes/1]).
-define(is_allowed_key(Key), (is_atom(Key) orelse (is_binary(Key) andalso Key =/= <<"">>))).
-define(is_allowed_value(Value), (is_atom(Value) orelse
is_boolean(Value) orelse
is_number(Value) orelse
is_binary(Value) orelse
is_list(Value))).
-record(attributes, {
count_limit :: integer(),
value_length_limit :: integer() | infinity,
dropped :: integer(),
map :: map()
}).
-type t() :: #attributes{}.
-export_type([t/0]).
%% @doc Creates a new `Attributes' from `Pairs' with the given count and value length limits.
%%
%% `Pairs' can be a list of key-value pairs or a map. If `Pairs' is not a list or map, the
%% function returns an empty `Attributes'.
-spec new(
[opentelemetry:attribute()] | opentelemetry:attributes_map(),
integer(),
integer() | infinity
) -> t().
new(Pairs, CountLimit, ValueLengthLimit) when is_list(Pairs) ->
new(maps:from_list(Pairs), CountLimit, ValueLengthLimit);
new(Map, CountLimit, ValueLengthLimit) when is_map(Map) ->
update_attributes(Map, #attributes{count_limit=CountLimit,
value_length_limit=ValueLengthLimit,
dropped=0,
map=#{}});
new(_, CountLimit, ValueLengthLimit) ->
#attributes{count_limit=CountLimit,
value_length_limit=ValueLengthLimit,
dropped=0,
map=#{}}.
%% @doc Sets the given key-value pairs in the given `Attributes'. Overrides
%% the existing value for a given key if it already exists in `Attributes'.
%%
%% `NewListOrMap' can be a list of key-value pairs or a map. If `NewListOrMap' is not a list
%% or map, the function returns `Attributes' as is. Returns the updated `Attributes'.
-spec set([opentelemetry:attribute()] | opentelemetry:attributes_map(), t()) -> t().
set(NewListOrMap, Attributes) when is_list(NewListOrMap) ->
set(maps:from_list(NewListOrMap), Attributes);
set(NewMap, Attributes) when is_map(NewMap) ->
update_attributes(NewMap, Attributes);
set(_, Attributes) ->
Attributes.
%% @doc Sets the given key-value pair in the given `Attributes'.
%%
%% Overrides the existing value under `Key' if `Key' already exists.
%% Returns the updated `Attributes'.
-spec set(opentelemetry:attribute_key(), opentelemetry:attribute_value(), t()) -> t().
set(Key, Value, Attributes) ->
update_attribute(Key, Value, Attributes).
%% @doc Returns the count of dropped attributes in the given `Attributes'.
dropped(#attributes{dropped=Dropped}) ->
Dropped.
%% @doc Returns the Attributes in the form of a map.
%%
%% For example:
%% ```
%% otel_attributes:new([], 10, 10),
%% otel_attributes:set(<<"key">>, <<"value">>, Attributes),
%% otel_attributes:map(Attributes).
%% %=> #{<<"key">> => <<"value">>}
%% '''
-spec map(t()) -> map().
map(#attributes{map=Map}) ->
Map.
%%
update_attributes(List, Attributes) ->
maps:fold(fun update_attribute/3, Attributes, List).
%% add key/value if the size is still under the limit or the key is already in the map
update_attribute(Key, Value, Attributes=#attributes{count_limit=CountLimit,
value_length_limit=ValueLengthLimit,
map=Map})
when is_binary(Value) , (map_size(Map) < CountLimit orelse is_map_key(Key, Map)) ->
Attributes#attributes{map=Map#{Key => maybe_truncate_binary(Value, ValueLengthLimit)}};
%% value is a list of binaries, so potentially truncate
update_attribute(Key, [Value1 | _Rest] = Value, Attributes=#attributes{count_limit=CountLimit,
value_length_limit=ValueLengthLimit,
map=Map})
when is_binary(Value1) , (map_size(Map) < CountLimit orelse is_map_key(Key, Map)) ->
Attributes#attributes{map=Map#{Key => [maybe_truncate_binary(V, ValueLengthLimit) || V <- Value]}};
%% already in the map and not a binary so update
update_attribute(Key, Value, Attributes=#attributes{map=Map}) when is_map_key(Key, Map) ->
Attributes#attributes{map=Map#{Key := Value}};
%% we've already started dropping, so just increment
update_attribute(_Key, _Value, Attributes=#attributes{dropped=Dropped})
when Dropped > 0 ->
Attributes#attributes{dropped=Dropped + 1};
%% met or exceeded the limit
update_attribute(_Key, _Value, Attributes=#attributes{count_limit=CountLimit,
dropped=Dropped,
map=Map})
when map_size(Map) >= CountLimit ->
Attributes#attributes{dropped=Dropped + 1};
%% new attribute
update_attribute(Key, Value, Attributes=#attributes{map=Map}) ->
Attributes#attributes{map=Map#{Key => Value}}.
maybe_truncate_binary(Value, infinity) ->
Value;
maybe_truncate_binary(Value, ValueLengthLimit) ->
case string:length(Value) > ValueLengthLimit of
true ->
string:slice(Value, 0, ValueLengthLimit);
false ->
Value
end.
%% @doc Checks whether the given key-value pair makes for a valid attribute.
%%
%% For example:
%% ```
%% otel_attributes:is_valid_attribute(<<"key">>, <<"value">>).
%% %=> true
%%
%% otel_attributes:is_valid_attribute(atom_key, <<"value">>).
%% %=> true
%%
%% otel_attributes:is_valid_attribute(123, <<"value">>).
%% %=> false
%% '''
-spec is_valid_attribute(opentelemetry:attribute_key(), opentelemetry:attribute_value()) -> boolean().
is_valid_attribute(Key, Value) when is_tuple(Value) , ?is_allowed_key(Key) ->
is_valid_attribute(Key, tuple_to_list(Value));
%% lists as attribute values must be primitive types and homogeneous
is_valid_attribute(Key, [Value1 | _Rest] = Values) when is_binary(Value1) , ?is_allowed_key(Key) ->
lists:all(fun is_binary/1, Values);
is_valid_attribute(Key, [Value1 | _Rest] = Values) when is_boolean(Value1) , ?is_allowed_key(Key) ->
lists:all(fun is_boolean/1, Values);
is_valid_attribute(Key, [Value1 | _Rest] = Values) when is_atom(Value1) , ?is_allowed_key(Key) ->
lists:all(fun is_valid_atom_value/1, Values);
is_valid_attribute(Key, [Value1 | _Rest] = Values) when is_integer(Value1) , ?is_allowed_key(Key) ->
lists:all(fun is_integer/1, Values);
is_valid_attribute(Key, [Value1 | _Rest] = Values) when is_float(Value1) , ?is_allowed_key(Key) ->
lists:all(fun is_float/1, Values);
is_valid_attribute(_Key, Value) when is_list(Value) ->
false;
is_valid_attribute(Key, []) when ?is_allowed_key(Key) ->
true;
is_valid_attribute(Key, Value) when ?is_allowed_key(Key) , ?is_allowed_value(Value) ->
true;
is_valid_attribute(_, _) ->
false.
is_valid_atom_value(undefined) ->
false;
is_valid_atom_value(nil) ->
false;
is_valid_atom_value(Value) ->
is_atom(Value) andalso (is_boolean(Value) == false).
%% @private
-spec process_attributes(eqwalizer:dynamic()) -> opentelemetry:attributes_map().
process_attributes(Attributes) when is_map(Attributes) ->
maps:fold(fun process_attribute/3, #{}, Attributes);
process_attributes([]) -> #{};
process_attributes(Attributes) when is_list(Attributes) ->
process_attributes(maps:from_list(Attributes));
process_attributes(_) ->
#{}.
process_attribute(Key, Value, Map) when is_tuple(Value) ->
List = tuple_to_list(Value),
case is_valid_attribute(Key, List) of
true ->
maps:put(Key, Value, Map);
false ->
Map
end;
process_attribute(Key, Value, Map) ->
case is_valid_attribute(Key, Value) of
true ->
maps:put(Key, Value, Map);
false ->
Map
end.

View File

@ -0,0 +1,240 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc Baggage is used to annotate telemetry, adding context and
%% information to metrics, traces, and logs. It is represented by a set
%% of name/value pairs describing user-defined properties.
%%
%% The baggage can be stored either in the <i>current context</i> (with {@link set/1} or
%% {@link set/3}, for example) or in an explicit Context (see {@link otel_ctx}).
%% @end
%%%-------------------------------------------------------------------------
-module(otel_baggage).
-export([set/1,
set/2,
set/3,
set/4,
set_to/2,
set_to/3,
set_to/4,
get_all/0,
get_all/1,
clear/0,
clear/1]).
%% Keys and values are UTF-8 binaries
-type key() :: unicode:unicode_binary().
%% The type for the baggage key, which is a UTF-8 binary.
-type value() :: unicode:unicode_binary().
%% The type for the baggage value, which is a UTF-8 binary.
-type input_key() :: key() | unicode:charlist().
%% An input key, that is, a key that is then converted to a UTF-8 binary.
-type input_value() :: value() | unicode:charlist() | atom().
%% An input value, that is, a value that is then converted to a UTF-8 binary.
-type metadata() :: [unicode:unicode_binary() | {unicode:unicode_binary(), unicode:unicode_binary()}].
%% The type for the baggage metadata, which is a list of UTF-8 binaries or a list of
%% tuples of UTF-8 binaries (as key-value pairs).
-type t() :: #{key() => {value(), metadata()}}.
%% The type for the baggage.
-export_type([t/0,
key/0,
value/0]).
-define(BAGGAGE_KEY, '$__otel_baggage_ctx_key').
-include("gradualizer.hrl").
%% @doc Sets the given key-value pairs in the current baggage.
%%
%% If you need to set <i>metadata</i> for the key-value pair, use {@link set/3} instead.
-spec set(#{key() => value()} | [{key(), value()}]) -> ok.
set(KeyValues) when is_list(KeyValues) ->
set(maps:from_list(KeyValues));
set(KeyValues) when is_map(KeyValues) ->
Baggage = otel_ctx:get_value(?BAGGAGE_KEY, #{}),
otel_ctx:set_value(?BAGGAGE_KEY, maps:merge(Baggage, verify_baggage(KeyValues)));
set(_) ->
ok.
%% @doc Sets the given key-value pair in the current baggage, or sets the
%% given key-value pairs in the baggage for the given context.
%%
%% Returns `ok' when using the `set(Key, Value)' form, or the updated context when
%% using the `set(Ctx, KeyValues)' form.
%% @end
%% Ctx will never be a list or binary so we can tell if a context is passed by checking that
-spec set(otel_ctx:t() | input_key(), #{input_key() => input_value()} | [{input_key(), input_value()}] | input_value()) -> otel_ctx:t() | ok.
set(Key, Value) when (is_list(Key) orelse is_binary(Key)) andalso is_binary(Value) ->
?assert_type(set(Key, Value, []), ok | undefined | #{any() => any()});
%% drop bad value
set(Key, Value) when (is_list(Key) orelse is_binary(Key)) andalso not is_binary(Value) ->
ok;
set(Ctx, KeyValues) when is_list(KeyValues) ->
%% eqwalizer:ignore I know what I'm doing
?assert_type(set(Ctx, maps:from_list(KeyValues)), ok | undefined | #{any() => any()});
set(Ctx, KeyValues) when is_map(KeyValues) andalso (is_map(Ctx) orelse Ctx =:= undefined)->
Baggage = otel_ctx:get_value(Ctx, ?BAGGAGE_KEY, #{}),
otel_ctx:set_value(Ctx, ?BAGGAGE_KEY, maps:merge(Baggage, verify_baggage(KeyValues))).
%% @doc Sets the given key-value pairs in the baggage for the given context.
%%
%% Returns the updated context.
-spec set_to(otel_ctx:t(), #{input_key() => input_value()} | [{input_key(), input_value()}]) -> otel_ctx:t().
set_to(Ctx, KeyValues) when is_list(KeyValues) ->
set_to(Ctx, maps:from_list(KeyValues));
set_to(Ctx, KeyValues) when is_map(KeyValues) ->
Baggage = otel_ctx:get_value(Ctx, ?BAGGAGE_KEY, #{}),
otel_ctx:set_value(Ctx, ?BAGGAGE_KEY, maps:merge(Baggage, verify_baggage(KeyValues))).
%% @doc Sets the given key-value pair in the current baggage (with the
%% associated metadata), or sets the given key-value pair in the baggage for the
%% given context.
%%
%% Returns `ok' when using the `set(Key, Value, Metadata)' form, or the updated
%% context when using the `set(Ctx, Key, Value)' form.
-spec set(otel_ctx:t() | input_key(), input_key() | input_value(), input_value() | metadata()) -> otel_ctx:t() | ok.
set(Key, Value, Metadata) when (is_list(Key) orelse is_binary(Key)) andalso is_binary(Value) ->
Baggage = otel_ctx:get_value(?BAGGAGE_KEY, #{}),
otel_ctx:set_value(?BAGGAGE_KEY, maps:merge(Baggage, verify_baggage(#{Key => {Value, Metadata}})));
%% drop bad value
set(Key, Value, _Metadata) when (is_list(Key) orelse is_binary(Key)) andalso not is_binary(Value) ->
ok;
set(Ctx, Key, Value) ->
set_to(?assert_type(Ctx, otel_ctx:t()),
?assert_type(Key, input_key()),
?assert_type(Value, input_value()),
[]).
%% @doc Sets the given key-value pair in the baggage for the given context.
%%
%% Returns the updated context.
-spec set_to(otel_ctx:t(), input_key(), input_value()) -> otel_ctx:t().
set_to(Ctx, Key, Value) ->
set_to(Ctx, Key, Value, []).
%% @doc Sets the given key-value pair in the baggage for the given context, with the
%% associated metadata.
%%
%% Returns the updated context.
-spec set(otel_ctx:t(), input_key(), input_value(), metadata()) -> otel_ctx:t().
set(Ctx, Key, Value, Metadata) when is_binary(Value) ->
Baggage = otel_ctx:get_value(Ctx, ?BAGGAGE_KEY, #{}),
otel_ctx:set_value(Ctx, ?BAGGAGE_KEY, maps:merge(Baggage, verify_baggage(#{Key => {Value, Metadata}})));
%% drop bad value
set(Ctx, _, _, _) ->
Ctx.
%% @doc Sets the given key-value pair in the baggage for the given context, with the
%% associated metadata.
%%
%% Returns the updated context.
-spec set_to(otel_ctx:t(), input_key(), input_value(), metadata()) -> otel_ctx:t().
set_to(Ctx, Key, Value, Metadata) when is_binary(Value) ->
Baggage = otel_ctx:get_value(Ctx, ?BAGGAGE_KEY, #{}),
otel_ctx:set_value(Ctx, ?BAGGAGE_KEY, maps:merge(Baggage, verify_baggage(#{Key => {Value, Metadata}})));
%% drop bad value
set_to(Ctx, _, _, _) ->
Ctx.
%% @doc Returns the baggage from the process dictionary.
-spec get_all() -> t().
get_all() ->
otel_ctx:get_value(?BAGGAGE_KEY, #{}).
%% @doc Returns the baggage for the given context.
-spec get_all(otel_ctx:t()) -> t().
get_all(Ctx) ->
otel_ctx:get_value(Ctx, ?BAGGAGE_KEY, #{}).
%% @doc Clears the baggage, removing all the current key-value pairs.
-spec clear() -> ok.
clear() ->
otel_ctx:set_value(?BAGGAGE_KEY, #{}).
%% @doc Clears the baggage for the given context, removing all the current key-value pairs.
-spec clear(otel_ctx:t()) -> otel_ctx:t().
clear(Ctx) ->
otel_ctx:set_value(Ctx, ?BAGGAGE_KEY, #{}).
%%
%% checks the keys, values and metadata are valid and drops them if they are not
%% all strings are converted to binaries
verify_baggage(KeyValues) ->
maps:fold(fun(K, V, Acc) ->
%% TODO: filter out keys with invalid characters here
case to_binary(K) of
error ->
Acc;
BinKey ->
case update_metadata(V) of
{true, ValueMetadata} ->
Acc#{BinKey => ValueMetadata};
_ ->
Acc
end
end
end, #{}, KeyValues).
to_binary(String) when is_list(String)->
%% wrap in a `try' in case the list is not a printable list
%% this can go away if we start checking the key with a regex
%% to ensure it only contains certain characters
try unicode:characters_to_binary(String) catch _:_ -> error end;
to_binary(String) when is_atom(String) ->
atom_to_binary(String, utf8);
to_binary(String) when is_binary(String) ->
String;
to_binary(_) ->
error.
update_metadata({Value, Metadata}) when is_list(Value) ->
case to_binary(Value) of
error ->
false;
BinValue ->
update_metadata(BinValue, Metadata)
end;
update_metadata(Value) when is_list(Value) ->
case to_binary(Value) of
error ->
false;
BinValue ->
update_metadata(BinValue, [])
end;
update_metadata({Value, Metadata}) ->
update_metadata(Value, Metadata);
update_metadata(Value) ->
update_metadata(Value, []).
update_metadata(Value, Metadata) when (is_binary(Value) orelse is_list(Value)) andalso is_list(Metadata) ->
{true, {Value, lists:filtermap(fun verify_metadata/1, Metadata)}};
update_metadata(_, _) ->
false.
verify_metadata({MK, MV}) when is_binary(MK) , is_binary(MV) ->
true;
verify_metadata(M) when is_binary(M) ->
true;
verify_metadata(_) ->
false.

View File

@ -0,0 +1,209 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc Ctx is responsible for propagating values within a process that
%% are associated with a particular Trace or set of Baggage.
%% `OpenTelemetry.Tracer' and `OpenTelemetry.Baggage' handle updating
%% the Context.
%%
%% Functions in this module include variants that explicitly take a `Ctx'
%% argument and variants that implicitly use the <i>current context</i>, which is
%% the context stored in the process dictionary.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_ctx).
-export([new/0,
set_value/2,
set_value/3,
get_value/1,
get_value/2,
get_value/3,
remove/1,
remove/2,
clear/0,
clear/1,
attach/1,
detach/1,
with_ctx/2,
get_current/0,
text_map_extractor/2,
text_map_injector/2,
text_map_extractor_fun/3,
text_map_injector_fun/3]).
-type t() :: map() | undefined.
%% A context map.
-type key() :: term().
%% A context key.
-type value() :: term().
%% A context value.
%% at this time the "token" is actually the context map itself
-opaque token() :: t().
%% An opaque token that represents a context.
-export_type([t/0,
token/0,
key/0,
value/0
]).
-define(CURRENT_CTX, '$__current_otel_ctx').
%% @doc Creates a new context.
-spec new() -> t().
new() ->
#{}.
%% @doc Sets a value in the current context under the given key.
-spec set_value(term(), term()) -> ok.
set_value(Key, Value) ->
erlang:put(?CURRENT_CTX, set_value(erlang:get(?CURRENT_CTX), Key, Value)),
ok.
%% @doc Sets a value in the given context under the given key.
%%
%% Returns the updated context.
-spec set_value(t(), term(), term()) -> t().
set_value(Ctx, Key, Value) when is_map(Ctx) ->
Ctx#{Key => Value};
set_value(_, Key, Value) ->
#{Key => Value}.
%% @doc Gets a value from the current context under the given key.
-spec get_value(term()) -> eqwalizer:dynamic().
get_value(Key) ->
get_value(erlang:get(?CURRENT_CTX), Key, undefined).
%% @doc Gets a value from the current context under the given key, or returns the default value
%% if the key is not present in the current context.
-spec get_value(term(), term()) -> eqwalizer:dynamic().
get_value(Key, Default) ->
get_value(erlang:get(?CURRENT_CTX), Key, Default).
%% @doc Gets a value from the given context under the given key, or returns the default value
%% if the key is not present in the given context or if `Ctx' is `undefined'.
-spec get_value(t(), term(), term()) -> eqwalizer:dynamic().
get_value(undefined, _Key, Default) ->
Default;
get_value(Ctx, Key, Default) when is_map(Ctx) ->
maps:get(Key, Ctx, Default);
get_value(_, _, Default) ->
Default.
%% @doc Removes all key-value pairs from the current context.
-spec clear() -> ok.
clear() ->
erlang:erase(?CURRENT_CTX),
ok.
%% @doc Removes all key-value pairs from the given context.
%%
%% Returns an empty context.
-spec clear(t()) -> t().
clear(_Ctx) ->
new().
%% @doc Removes the value under the given key from the current context.
-spec remove(term()) -> ok.
remove(Key) ->
case erlang:get(?CURRENT_CTX) of
Map when is_map(Map) ->
erlang:put(?CURRENT_CTX, maps:remove(Key, Map)),
ok;
_ ->
ok
end.
%% @doc Removes the value under the given key from the given context.
%%
%% Returns the updated context.
-spec remove(t(), term()) -> t().
remove(Ctx, Key) when is_map(Ctx) ->
maps:remove(Key, Ctx);
remove(_, _) ->
new().
%% @doc Returns the current context.
-spec get_current() -> map().
get_current() ->
case erlang:get(?CURRENT_CTX) of
Map when is_map(Map) ->
Map;
_ ->
#{}
end.
%% @doc Attaches the given context to the current process.
%%
%% Essentially, this sets `Ctx' as the <i>current context</i>
%% .
-spec attach(t()) -> token().
attach(Ctx) ->
update_logger_process_metadata(Ctx),
erlang:put(?CURRENT_CTX, Ctx).
%% @doc Detaches the given context from the current process.
-spec detach(token()) -> t() | undefined.
detach(Token) ->
%% at this time `Token' is a context
update_logger_process_metadata(Token),
erlang:put(?CURRENT_CTX, Token).
%% @doc Attaches a context and runs a function, detaching the context at the end.
%%
%% Returns the detached context.
-spec with_ctx(t(), fun(() -> term())) -> {term(), t()}.
with_ctx(Ctx, Fun) ->
Token = otel_ctx:attach(Ctx),
try
Result = Fun(),
{Result, otel_ctx:detach(Token)}
catch
C:T:S ->
otel_ctx:detach(Token),
erlang:raise(C, T, S)
end.
%% Extractor and Injector setup functions
%% @private
text_map_extractor(Key, FromText) ->
{fun ?MODULE:text_map_extractor_fun/3, {Key, FromText}}.
%% @private
text_map_extractor_fun(TextMap, Key, FromText) ->
New = FromText(TextMap, ?MODULE:get_value(Key, #{})),
?MODULE:set_value(Key, New).
%% @private
text_map_injector(Key, ToText) ->
{fun ?MODULE:text_map_injector_fun/3, {Key, ToText}}.
%% @private
text_map_injector_fun(TextMap, Key, ToText) ->
TextMap ++ ToText(?MODULE:get_value(Key, undefined)).
%%
update_logger_process_metadata(undefined) ->
ok;
update_logger_process_metadata(Ctx) ->
otel_tracer:update_logger_process_metadata(Ctx).

View File

@ -0,0 +1,91 @@
%%%------------------------------------------------------------------------
%% Copyright 2020, OpenTelemetry Authors
%% 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.
%%
%% @doc A Propagator injects or extracts data from a Context so information
%% like baggage and trace context can be transported along with cross service
%% requests, like an HTTP request.
%%
%% Propagators are defined based on the type of encoding they inject and
%% extract. At this time there is only a TextMapPropagator,
%% {@link otel_propagator_text_map}, which works on ASCII keys and values.
%%
%% This behaviour is only for defining the callbacks used by each propagator
%% per type and is only used by developers adding a new type of propagator
%% (like for binary protocols), not implementations of propagators themselves
%% (like B3 or W3C TraceContext).
%%
%% Users configure and call propagators based on their type. See the docs
%% for {@link otel_propagator_text_map} for more details.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_propagator).
-export([builtins_to_modules/1,
builtin_to_module/1]).
-callback inject(t(), carrier()) -> carrier().
%% Sets a value into a carrier.
-callback inject_from(otel_ctx:t(), t(), carrier()) -> carrier().
%% Sets a value from a context into a carrier.
-callback extract(t(), carrier()) -> otel_ctx:t() | otel_ctx:token().
%% Extracts a value from a carrier.
-callback extract_to(otel_ctx:t(), t(), carrier()) -> otel_ctx:t().
%% Extracts a value from a carrier into a context.
-type t() :: builtin() | module() | {module(), term()}.
%% A propagator, which can be a built-in propagator, a module, or a module
%% and associated term.
%% trace_context and tracecontext are the same. tracecontext is the term
%% in Otel specs and trace_context is the more idiomatic Erlang spelling
%% In the future, also: jaeger
-type builtin() :: trace_context | tracecontext | b3 | b3multi | baggage.
%% A built-in propagator.
-type carrier() :: term().
%% A carrier, which can be any type.
-export_type([t/0,
builtin/0,
carrier/0]).
%% convert the short name of a propagator to its module name if it is a builtin
%% if the name doesn't match a builtin it is assumed to be a module
%% @private
-spec builtins_to_modules([t()]) -> [module() | {module(), term()}].
builtins_to_modules(Propagators) ->
[builtin_to_module(P) || P <- Propagators].
%% @private
-spec builtin_to_module(builtin() | module() | {module(), term()}) -> module() | {module(), term()}.
builtin_to_module(tracecontext) ->
otel_propagator_trace_context;
builtin_to_module(trace_context) ->
otel_propagator_trace_context;
builtin_to_module(b3) ->
{otel_propagator_b3, b3single};
builtin_to_module(b3multi) ->
{otel_propagator_b3, b3multi};
builtin_to_module(baggage) ->
otel_propagator_baggage;
%% TODO: add jaeger as builtin propagator
%% builtin_to_module(jaeger) ->
%% otel_propagator_jaeger;
builtin_to_module(Module) when is_atom(Module) ->
Module;
builtin_to_module(Propagator) ->
Propagator.

View File

@ -0,0 +1,114 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc An implementation of {@link otel_propagator_text_map} that injects and
%% extracts trace context using the B3 specification from Zipkin.
%%
%% Since `trace_context' and `baggage' are the two default propagators, the
%% global TextMap Propagators must be configured if B3 is to be used for
%% propagation:
%%
%% ```
%% {text_map_propagators, [b3, baggage]},
%% '''
%%
%% To use B3 multi-header format use:
%%
%% ```
%% {text_map_propagators, [b3multi, baggage]},
%% '''
%%
%% ```
%% CompositePropagator = otel_propagator_text_map_composite:create([b3, baggage]),
%% opentelemetry:set_text_map_propagator(CompositePropagator).
%% '''
%%
%% It is also possible to set a separate list of injectors or extractors.
%% For example, if the service should extract B3 encoded context but you
%% only want to inject context encoded with the W3C TraceContext format
%% (maybe you have some services only supporting B3 that are making requests
%% to your server but you have no reason to continue propagating in both
%% formats when communicating to other services further down the stack).
%% In that case you would instead set configuration like:
%%
%%
%% ```
%% {text_map_extractors, [b3, trace_context, baggage]},
%% {text_map_injectors, [trace_context, baggage]},
%% '''
%%
%% Or using calls to {@link opentelemetry} at runtime:
%%
%% ```
%% B3CompositePropagator = otel_propagator_text_map_composite:create([b3, trace_context, baggage]),
%% CompositePropagator = otel_propagator_text_map_composite:create([trace_context, baggage]),
%% opentelemetry:set_text_map_extractor(B3CompositePropagator),
%% opentelemetry:set_text_map_injector(CompositePropagator).
%% '''
%% @end
%%%-----------------------------------------------------------------------
-module(otel_propagator_b3).
-behaviour(otel_propagator_text_map).
-export([fields/1,
inject/4,
extract/5]).
-include("opentelemetry.hrl").
-define(B3_CONTEXT_KEY, <<"b3">>).
%% Returns all the keys the propagator sets with `inject'
%% @private
fields(b3single) ->
otel_propagator_b3single:fields(b3single);
fields(b3multi) ->
otel_propagator_b3multi:fields(b3multi);
fields(_) ->
[].
%% @private
-spec inject(Context, Carrier, CarrierSetFun, Options) -> Carrier
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierSetFun :: otel_propagator_text_map:carrier_set(),
Options :: b3multi | b3single.
inject(Ctx, Carrier, CarrierSet, Options=b3single) ->
otel_propagator_b3single:inject(Ctx, Carrier, CarrierSet, Options);
inject(Ctx, Carrier, CarrierSet, Options=b3multi) ->
otel_propagator_b3multi:inject(Ctx, Carrier, CarrierSet, Options);
inject(_Ctx, Carrier, _CarrierSet, _Options) ->
Carrier.
% Extract trace context from the supplied carrier. The b3 single header takes
% precedence over the multi-header format.
%
% If extraction fails, the original context will be returned.
%% @private
-spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Options) -> Context
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierKeysFun :: otel_propagator_text_map:carrier_keys(),
CarrierGetFun :: otel_propagator_text_map:carrier_get(),
Options :: otel_propagator_text_map:propagator_options().
extract(Ctx, Carrier, CarrierKeysFun, CarrierGet, Options) ->
case otel_propagator_b3single:extract(Ctx, Carrier, CarrierKeysFun, CarrierGet, Options) of
Result when Result =/= undefined -> Result;
_ ->
case otel_propagator_b3multi:extract(Ctx, Carrier, CarrierKeysFun, CarrierGet, Options) of
Result when Result =/= undefined -> Result;
_ -> Ctx
end
end.

View File

@ -0,0 +1,138 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc An implementation of {@link otel_propagator_text_map} that injects and
%% extracts trace context using the B3 multi header format specification from
%% Zipkin.
%%
%% @see otel_propagator_b3
%% @end
%%%-----------------------------------------------------------------------
-module(otel_propagator_b3multi).
-behaviour(otel_propagator_text_map).
-export([fields/1,
inject/4,
extract/5]).
-include("opentelemetry.hrl").
-define(B3_TRACE_ID, <<"X-B3-TraceId">>).
-define(B3_SPAN_ID, <<"X-B3-SpanId">>).
-define(B3_SAMPLED, <<"X-B3-Sampled">>).
%% @private
fields(_) ->
[?B3_TRACE_ID, ?B3_SPAN_ID, ?B3_SAMPLED].
%% @private
-spec inject(Context, Carrier, CarrierSetFun, Options) -> Carrier
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierSetFun :: otel_propagator_text_map:carrier_set(),
Options :: otel_propagator_text_map:propagator_options().
inject(Ctx, Carrier, CarrierSet, _Options) ->
case otel_tracer:current_span_ctx(Ctx) of
#span_ctx{trace_id=TraceId,
span_id=SpanId,
trace_flags=TraceOptions} when TraceId =/= 0, SpanId =/= 0 ->
Options = case TraceOptions band 1 of 1 -> <<"1">>; _ -> <<"0">> end,
EncodedTraceId = io_lib:format("~32.16.0b", [TraceId]),
EncodedSpanId = io_lib:format("~16.16.0b", [SpanId]),
case {unicode:characters_to_binary(EncodedTraceId),
unicode:characters_to_binary(EncodedSpanId)} of
{BinTraceId, BinSpanId} when is_binary(BinTraceId) , is_binary(BinSpanId) ->
CarrierSet(?B3_TRACE_ID, BinTraceId,
CarrierSet(?B3_SPAN_ID, BinSpanId,
CarrierSet(?B3_SAMPLED, Options, Carrier)));
_ ->
Carrier
end;
_ ->
Carrier
end.
% Extract trace context from the supplied carrier. The b3 single header takes
% precedence over the multi-header format.
%
% If extraction fails, the original context will be returned.
%% @private
-spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Options) -> Context
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierKeysFun :: otel_propagator_text_map:carrier_keys(),
CarrierGetFun :: otel_propagator_text_map:carrier_get(),
Options :: otel_propagator_text_map:propagator_options().
extract(Ctx, Carrier, _CarrierKeysFun, CarrierGet, _Options) ->
try
TraceId = parse_trace_id(CarrierGet(?B3_TRACE_ID, Carrier)),
SpanId = parse_span_id(CarrierGet(?B3_SPAN_ID, Carrier)),
Sampled = parse_is_sampled(CarrierGet(?B3_SAMPLED, Carrier)),
SpanCtx = otel_tracer:from_remote_span(TraceId, SpanId, Sampled),
otel_tracer:set_current_span(Ctx, SpanCtx)
catch
throw:invalid ->
undefined;
%% thrown if _to_integer fails or an invalid string encoding is sent
error:badarg ->
undefined
end.
% Trace ID is a 32 or 16 lower-hex character binary.
parse_trace_id(TraceId) when is_binary(TraceId) ->
case string:length(TraceId) =:= 32 orelse string:length(TraceId) =:= 16 of
true -> string_to_integer(TraceId, 16);
_ -> throw(invalid)
end;
parse_trace_id(_) ->
throw(invalid).
% Span ID is a 16 lower-hex character binary.
parse_span_id(SpanId) when is_binary(SpanId) ->
case string:length(SpanId) =:= 16 of
true -> string_to_integer(SpanId, 16);
_ -> throw(invalid)
end;
parse_span_id(_) ->
throw(invalid).
% Sampling State is encoded as a single hex character for all states except
% Defer. Defer is absence of the sampling field.
%
% Possible states:
% 1 - accept
% 0 - deny
% d - debug (not supported at the moment, we instead used accept)
%
% Before the specification was written, some tracers propagated X-B3-Sampled as
% true or false.
parse_is_sampled(Sampled) when is_binary(Sampled) ->
case Sampled of
S when S =:= <<"1">> orelse S =:= <<"d">> orelse S =:= <<"true">> -> 1;
S when S =:= <<"0">> orelse S =:= <<"false">> -> 0;
_ -> throw(invalid)
end;
parse_is_sampled(undefined) ->
% Sampled flag is optional. If it's missing then the sampling decision is
% deferred. We don't currently support it and just set the flag to 0
% instead (similarly how some other OTEL implementations are doing).
0;
parse_is_sampled(_) ->
throw(invalid).
string_to_integer(S, Base) when is_binary(S) ->
binary_to_integer(S, Base).

View File

@ -0,0 +1,144 @@
%%%------------------------------------------------------------------------
%% Copyright 2019, OpenTelemetry Authors
%% 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.
%%
%% @doc An implementation of {@link otel_propagator_text_map} that injects and
%% extracts trace context using the B3 single header format specification from
%% Zipkin.
%%
%% @see otel_propagator_b3
%% @end
%%%-----------------------------------------------------------------------
-module(otel_propagator_b3single).
-behaviour(otel_propagator_text_map).
-export([fields/1,
inject/4,
extract/5]).
-include("opentelemetry.hrl").
-define(B3_CONTEXT_KEY, <<"b3">>).
%% @private
fields(_) ->
[?B3_CONTEXT_KEY].
%% @private
-spec inject(Context, Carrier, CarrierSetFun, Options) -> Carrier
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierSetFun :: otel_propagator_text_map:carrier_set(),
Options :: otel_propagator_text_map:propagator_options().
inject(Ctx, Carrier, CarrierSet, _Options) ->
case otel_tracer:current_span_ctx(Ctx) of
#span_ctx{trace_id=TraceId,
span_id=SpanId,
trace_flags=TraceOptions} when TraceId =/= 0, SpanId =/= 0 ->
Options = case TraceOptions band 1 of 1 -> <<"1">>; _ -> <<"0">> end,
EncodedTraceId = io_lib:format("~32.16.0b", [TraceId]),
EncodedSpanId = io_lib:format("~16.16.0b", [SpanId]),
B3Context = otel_utils:assert_to_binary([EncodedTraceId, "-",
EncodedSpanId, "-", Options]),
CarrierSet(?B3_CONTEXT_KEY, B3Context, Carrier);
_ ->
Carrier
end.
%% @private
-spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Options) -> Context
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierKeysFun :: otel_propagator_text_map:carrier_keys(),
CarrierGetFun :: otel_propagator_text_map:carrier_get(),
Options :: otel_propagator_text_map:propagator_options().
extract(Ctx, Carrier, _CarrierKeysFun, CarrierGet, _Options) ->
try
[TraceId, SpanId, Sampled] = parse_b3_context(Carrier, CarrierGet),
SpanCtx = otel_tracer:from_remote_span(TraceId, SpanId, Sampled),
otel_tracer:set_current_span(Ctx, SpanCtx)
catch
throw:invalid ->
undefined;
%% thrown if _to_integer fails or an invalid string encoding is sent
error:badarg ->
undefined
end.
% B3 maps propagation fields into a hyphen delimited string:
% {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}, where the last two fields are optional.
%
% When only propagating a sampling decision, the header is still named b3, but
% only contains the sampling state:
% {SamplingState}
parse_b3_context(Carrier, CarrierGet) ->
case CarrierGet(?B3_CONTEXT_KEY, Carrier) of
B3Context when is_binary(B3Context) ->
decode_b3_context(string:split(B3Context, "-", all));
_ ->
throw(invalid)
end.
decode_b3_context([TraceId, SpanId]) ->
% Sampled flag is optional. If it's missing then the sampling decision is
% deferred. We don't currently support it and just set the flag to 0
% instead (similarly how some other OTEL implementations are doing).
[parse_trace_id(TraceId), parse_span_id(SpanId), 0];
decode_b3_context([TraceId, SpanId, Sampled]) ->
[parse_trace_id(TraceId), parse_span_id(SpanId), parse_is_sampled(Sampled)];
decode_b3_context([TraceId, SpanId, Sampled, _ParentSpanId]) ->
[parse_trace_id(TraceId), parse_span_id(SpanId), parse_is_sampled(Sampled)];
decode_b3_context(_) ->
throw(invalid).
% Trace ID is a 32 or 16 lower-hex character binary.
parse_trace_id(TraceId) when is_binary(TraceId) ->
case string:length(TraceId) =:= 32 orelse string:length(TraceId) =:= 16 of
true -> string_to_integer(TraceId, 16);
_ -> throw(invalid)
end;
parse_trace_id(_) ->
throw(invalid).
% Span ID is a 16 lower-hex character binary.
parse_span_id(SpanId) when is_binary(SpanId) ->
case string:length(SpanId) =:= 16 of
true -> string_to_integer(SpanId, 16);
_ -> throw(invalid)
end;
parse_span_id(_) ->
throw(invalid).
% Sampling State is encoded as a single hex character for all states except
% Defer. Defer is absence of the sampling field.
%
% Possible states:
% 1 - accept
% 0 - deny
% d - debug (not supported at the moment, we instead used accept)
%
% Before the specification was written, some tracers propagated X-B3-Sampled as
% true or false.
parse_is_sampled(Sampled) when is_binary(Sampled) ->
case Sampled of
S when S =:= <<"1">> orelse S =:= <<"d">> orelse S =:= <<"true">> -> 1;
S when S =:= <<"0">> orelse S =:= <<"false">> -> 0;
_ -> throw(invalid)
end;
parse_is_sampled(_) ->
throw(invalid).
string_to_integer(S, Base) when is_binary(S) ->
binary_to_integer(S, Base).

View File

@ -0,0 +1,241 @@
%%%------------------------------------------------------------------------
%% Copyright 2021, OpenTelemetry Authors
%% 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.
%%
%% @doc An implementation of {@link otel_propagator_text_map} that injects and
%% extracts baggage using the
%% <a href="https://w3c.github.io/baggage/">W3C Baggage format</a>.
%%
%% This propagator along with {@link otel_propagator_trace_context} are used
%% by default. The global TextMap Propagators can be configured in the
%% application environment:
%%
%% ```
%% {text_map_propagators, [trace_context, baggage]},
%% '''
%%
%% Or by calling {@link opentelemetry:set_text_map_propagator/1}.
%% @end
%%%-----------------------------------------------------------------------
-module(otel_propagator_baggage).
-behaviour(otel_propagator_text_map).
-export([fields/1,
inject/4,
extract/5]).
-include("opentelemetry.hrl").
-define(DEC2HEX(X),
if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0;
((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10
end).
-define(HEX2DEC(X),
if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0;
((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10;
((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10
end).
-define(BAGGAGE_HEADER, <<"baggage">>).
%% @private
fields(_) ->
[?BAGGAGE_HEADER].
%% @private
-spec inject(Context, Carrier, CarrierSetFun, Options) -> Carrier
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierSetFun :: otel_propagator_text_map:carrier_set(),
Options :: otel_propagator_text_map:propagator_options().
inject(Ctx, Carrier, CarrierSet, _Options) ->
Baggage = otel_baggage:get_all(Ctx),
case maps:fold(fun(Key, Value, Acc) ->
[$,, [encode_key(Key), "=", encode_value(Value)] | Acc]
end, [], Baggage) of
[$, | List] ->
CarrierSet(?BAGGAGE_HEADER, otel_utils:assert_to_binary(List), Carrier);
_ ->
Carrier
end.
%% @private
-spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Options) -> Context
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierKeysFun :: otel_propagator_text_map:carrier_keys(),
CarrierGetFun :: otel_propagator_text_map:carrier_get(),
Options :: otel_propagator_text_map:propagator_options().
extract(Ctx, Carrier, _CarrierKeysFun, CarrierGet, _Options) ->
case CarrierGet(?BAGGAGE_HEADER, Carrier) of
undefined ->
Ctx;
String ->
Pairs = string:lexemes(String, [$,]),
DecodedBaggage =
lists:foldl(fun(Pair, Acc) ->
[Key, Value] = string:split(Pair, "="),
Acc#{decode_key(Key) => decode_value(Value)}
end, #{}, Pairs),
otel_baggage:set_to(Ctx, DecodedBaggage)
end.
%%
encode_key(Key) ->
form_urlencode(Key, [{encoding, utf8}]).
encode_value({Value, Metadata}) ->
EncodedMetadata = encode_metadata(Metadata),
EncodedValue = form_urlencode(Value, [{encoding, utf8}]),
otel_utils:assert_to_binary(lists:join(<<";">>, [EncodedValue | EncodedMetadata])).
encode_metadata(Metadata) when is_list(Metadata) ->
lists:filtermap(fun({MK, MV}) when is_binary(MK) , is_binary(MV) ->
{true, [MK, <<"=">>, MV]};
(M) when is_binary(M) ->
{true, M};
(_) ->
false
end, Metadata);
encode_metadata(_) ->
[].
decode_key(Key) ->
percent_decode(string:trim(otel_utils:assert_to_binary(Key))).
decode_value(ValueAndMetadata) ->
[Value | MetadataList] = string:lexemes(ValueAndMetadata, [$;]),
{string_decode(Value), lists:filtermap(fun metadata_decode/1, MetadataList)}.
metadata_decode(Metadata) ->
case string:split(Metadata, "=") of
[MetadataKey] ->
{true, string_decode(MetadataKey)};
[MetadataKey, MetadataValue] ->
{true, {string_decode(MetadataKey), string_decode(MetadataValue)}};
_ ->
false
end.
string_decode(S) ->
percent_decode(string:trim(otel_utils:assert_to_binary(S))).
%% TODO: call `uri_string:percent_decode' and remove this when OTP-23 is
%% the oldest version we maintain support for
-spec percent_decode(URI) -> Result when
URI :: unicode:chardata(),
Result :: unicode:chardata() | uri_string:error().
percent_decode(URI) when is_list(URI) orelse
is_binary(URI) ->
raw_decode(URI).
%% TODO: call `uri_string:percent_encode' when it is added to OTP and
%% available in the oldest version we support
form_urlencode(Cs, [{encoding, Encoding}])
when is_list(Cs), Encoding =:= utf8; Encoding =:= unicode ->
B = convert_to_binary(Cs, utf8, Encoding),
html5_byte_encode(B);
form_urlencode(Cs, [{encoding, Encoding}])
when is_binary(Cs), Encoding =:= utf8; Encoding =:= unicode ->
html5_byte_encode(Cs);
form_urlencode(Cs, [{encoding, Encoding}]) when is_list(Cs); is_binary(Cs) ->
throw({error,invalid_encoding, Encoding});
form_urlencode(Cs, _) ->
throw({error,invalid_input, Cs}).
html5_byte_encode(B) ->
html5_byte_encode(B, <<>>).
%%
html5_byte_encode(<<>>, Acc) ->
Acc;
html5_byte_encode(<<$ ,T/binary>>, Acc) ->
html5_byte_encode(T, <<Acc/binary,$+>>);
html5_byte_encode(<<H,T/binary>>, Acc) ->
case is_url_char(H) of
true ->
html5_byte_encode(T, <<Acc/binary,H>>);
false ->
<<A:4,B:4>> = <<H>>,
html5_byte_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>)
end;
html5_byte_encode(H, _Acc) ->
throw({error,invalid_input, H}).
%% Return true if input char can appear in form-urlencoded string
%% Allowed chararacters:
%% 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A,
%% 0x5F, 0x61 to 0x7A
is_url_char(C)
when C =:= 16#2A; C =:= 16#2D;
C =:= 16#2E; C =:= 16#5F;
16#30 =< C, C =< 16#39;
16#41 =< C, C =< 16#5A;
16#61 =< C, C =< 16#7A -> true;
is_url_char(_) -> false.
%% Convert to binary
convert_to_binary(Binary, InEncoding, OutEncoding) ->
case unicode:characters_to_binary(Binary, InEncoding, OutEncoding) of
{error, _List, RestData} ->
throw({error, invalid_input, RestData});
{incomplete, _List, RestData} ->
throw({error, invalid_input, RestData});
Result ->
Result
end.
-spec raw_decode(list()|binary()) -> list() | binary() | uri_string:error().
raw_decode(Cs) ->
raw_decode(Cs, <<>>).
%%
raw_decode(L, Acc) when is_list(L) ->
try
B0 = otel_utils:assert_to_binary(L),
B1 = raw_decode(B0, Acc),
unicode:characters_to_list(B1)
catch
throw:{error, Atom, RestData} ->
{error, Atom, RestData}
end;
raw_decode(<<$%,C0,C1,Cs/binary>>, Acc) ->
case is_hex_digit(C0) andalso is_hex_digit(C1) of
true ->
B = ?HEX2DEC(C0)*16+?HEX2DEC(C1),
raw_decode(Cs, <<Acc/binary, B>>);
false ->
throw({error,invalid_percent_encoding,<<$%,C0,C1>>})
end;
raw_decode(<<C,Cs/binary>>, Acc) ->
raw_decode(Cs, <<Acc/binary, C>>);
raw_decode(<<>>, Acc) ->
check_utf8(Acc).
%% Returns Cs if it is utf8 encoded.
check_utf8(Cs) ->
case unicode:characters_to_list(Cs) of
{incomplete,_,_} ->
throw({error,invalid_utf8,Cs});
{error,_,_} ->
throw({error,invalid_utf8,Cs});
_ -> Cs
end.
-spec is_hex_digit(non_neg_integer()) -> boolean().
is_hex_digit(C)
when $0 =< C, C =< $9;$a =< C, C =< $f;$A =< C, C =< $F -> true;
is_hex_digit(_) -> false.

View File

@ -0,0 +1,244 @@
%%%------------------------------------------------------------------------
%% Copyright 2020, OpenTelemetry Authors
%% 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.
%%
%% @doc A TextMap Propagator is a Propagator that performs injection and
%% extraction with ASCII keys and values.
%%
%% An example of
%% configuring the TextMap Propagator to inject and extract Baggage and
%% TraceContext:
%%
%% ```
%% {text_map_propagators, [trace_context, baggage]},
%% '''
%%
%% The propagators are then used at the points that cross-service
%% communication is performed. By default, {@link inject/2} and {@link extract/2} work on a
%% generic list of 2-tuple's with binary string keys and values. You can pass (as an argument)
%% a user-defined function for setting a key/value in the carrier and for getting
%% the value of a key. For example, injecting and extracting to and from
%% <a href="https://github.com/benoitc/hackney">Hackney</a> headers could be
%% done with Hackney-specific functions:
%%
%% ```
%% set_header(Key, Value, Headers) ->
%% hackney_headers:store(Key, Value, Headers).
%%
%% some_fun_calling_hackney() ->
%% Headers = otel_propagator_text_map:inject(opentelemetry:get_text_map_injector(), hackney_headers:new(), fun set_header/2),
%% %% ...
%% '''
%%
%% An example of extraction in an <a href="https://github.com/elli-lib/elli">Elli</a> request
%% handler:
%%
%% ```
%% get_header(Req, Key) ->
%% elli_request:get_header(Key, Req, Default).
%%
%% handle(Req, _Args) ->
%% otel_propagator_text_map:extract(Req, fun get_header/2),
%% %% ...
%% {ok, [], <<"hello world">>}.
%% '''
%% @end
%%%-------------------------------------------------------------------------
-module(otel_propagator_text_map).
-behaviour(otel_propagator).
-export([fields/1,
inject/1,
inject/2,
inject/3,
inject_from/2,
inject_from/3,
inject_from/4,
extract/1,
extract/2,
extract/4,
extract_to/2,
extract_to/3,
extract_to/5]).
-export([default_carrier_get/2,
default_carrier_set/3,
default_carrier_keys/1]).
-include_lib("kernel/include/logger.hrl").
%% Sets a value into a carrier
-callback inject(otel_ctx:t(), otel_propagator:carrier(), carrier_set(), propagator_options()) -> otel_propagator:carrier().
%% Extracts values from a carrier and sets them in the context
-callback extract(otel_ctx:t(), otel_propagator:carrier(), carrier_keys(), carrier_get(), propagator_options()) -> term().
%% Returns all the keys the propagator sets with `inject'
-callback fields(propagator_options()) -> [field_key()].
%% a textmap propagator can have any term associated with it
-type propagator_options() :: term().
-type field_key() :: unicode:latin1_binary().
-type field_value() :: unicode:latin1_binary().
%% return all matching keys from the carrier
%% for example: with the jaeger propagation format this would be
%% all keys found with prefix "uberctx-"
-type carrier_keys() :: fun((otel_propagator:carrier()) -> [unicode:latin1_binary()]).
-type carrier_get() :: fun((unicode:latin1_binary(), otel_propagator:carrier()) -> unicode:latin1_binary() | undefined).
-type carrier_set() :: fun((unicode:latin1_binary(), unicode:latin1_binary(), otel_propagator:carrier()) -> otel_propagator:carrier()).
-type default_text_map_carrier() :: [{unicode:latin1_binary(), unicode:latin1_binary()}].
%% 2-tuple form is a textmap propagator with options
%% an empty list is passed for options if the propagator is a module with no options
-type t() :: module() | {module(), propagator_options()}.
-export_type([t/0,
carrier_set/0,
carrier_get/0,
carrier_keys/0,
propagator_options/0]).
%% @private
-spec fields(otel_propagator:t()) -> [field_key()].
fields(Propagator) when is_atom(Propagator) ->
Propagator:fields([]);
fields({Module, Options}) ->
Module:fields(Options).
%% @doc Injects `Carrier' into the current context using the current TextMap Propagator.
%%
%% @see inject/2
-spec inject(otel_propagator:carrier()) -> otel_propagator:carrier().
inject(Carrier) ->
Propagator = opentelemetry:get_text_map_injector(),
inject(Propagator, Carrier, fun default_carrier_set/3).
%% @doc Injects `Carrier' into the current context using the provided `Propagator'.
%%
%% By default, the `Carrier' is set using the a default carrier set function.
%% @see inject/3
-spec inject(otel_propagator:t(), otel_propagator:carrier()) -> otel_propagator:carrier().
inject(Propagator, Carrier) ->
inject(Propagator, Carrier, fun default_carrier_set/3).
%% @doc Injects `Carrier' (through `CarrierSetFun') into the current
%% context using the provided `Propagator'.
-spec inject(otel_propagator:t(), otel_propagator:carrier(), fun()) -> otel_propagator:carrier().
inject(Propagator, Carrier, CarrierSetFun) ->
Context = otel_ctx:get_current(),
inject_from(Context, Propagator, Carrier, CarrierSetFun).
%% @equiv inject_from(Context, opentelemetry:get_text_map_injector(), Carrier)
-spec inject_from(otel_ctx:t(), otel_propagator:carrier()) -> otel_propagator:carrier().
inject_from(Context, Carrier) ->
Propagator = opentelemetry:get_text_map_injector(),
inject_from(Context, Propagator, Carrier, fun default_carrier_set/3).
%% @equiv inject_from(Context, Propagator, Carrier, fun default_carrier_set/3)
-spec inject_from(otel_ctx:t(), otel_propagator:t(), otel_propagator:carrier()) -> otel_propagator:carrier().
inject_from(Context, Propagator, Carrier) ->
inject_from(Context, Propagator, Carrier, fun default_carrier_set/3).
%% @doc Injects `Carrier' (through `CarrierSetFun') into the given
%% `Context' using the provided propagator `Propagator'.
-spec inject_from(otel_ctx:t(), otel_propagator:t(), otel_propagator:carrier(), fun()) -> otel_propagator:carrier().
inject_from(Context, Propagator, Carrier, CarrierSetFun) when is_atom(Propagator) ->
Propagator:inject(Context, Carrier, CarrierSetFun, []);
inject_from(Context, {Propagator, Options}, Carrier, CarrierSetFun) ->
Propagator:inject(Context, Carrier, CarrierSetFun, Options).
%% @doc Extracts the current context from the provided `Carrier' using the current
%% TextMap Propagator.
-spec extract(otel_propagator:carrier()) -> otel_ctx:token().
extract(Carrier) ->
Propagator = opentelemetry:get_text_map_extractor(),
extract(Propagator, Carrier, fun default_carrier_keys/1, fun default_carrier_get/2).
%% @doc Extracts the current context from the provided `Carrier' using the
%% given `Propagator'.
-spec extract(otel_propagator:t(), otel_propagator:carrier()) -> otel_ctx:token().
extract(Propagator, Carrier) ->
extract(Propagator, Carrier, fun default_carrier_keys/1, fun default_carrier_get/2).
%% @doc Extracts the current context from the provided `Carrier' using the
%% given `Propagator' and functions to get all the keys and get the keys from the carrier.
-spec extract(otel_propagator:t(), otel_propagator:carrier(), fun(), fun()) -> otel_ctx:token().
extract(Propagator, Carrier, CarrierKeysFun, CarrierGetFun) ->
Context = otel_ctx:get_current(),
Context1 = extract_to(Context, Propagator, Carrier, CarrierKeysFun, CarrierGetFun),
otel_ctx:attach(Context1).
%% @equiv extract_to(Context, opentelemetry:get_text_map_extractor(), Carrier)
-spec extract_to(otel_ctx:t(), otel_propagator:carrier()) -> otel_ctx:t().
extract_to(Context, Carrier) ->
Propagator = opentelemetry:get_text_map_extractor(),
extract_to(Context, Propagator, Carrier, fun default_carrier_keys/1, fun default_carrier_get/2).
%% @equiv extract_to(Context, Propagator, Carrier, fun default_carrier_keys/1, fun default_carrier_get/2)
-spec extract_to(otel_ctx:t(), otel_propagator:t(), otel_propagator:carrier()) -> otel_ctx:t().
extract_to(Context, Propagator, Carrier) ->
extract_to(Context, Propagator, Carrier, fun default_carrier_keys/1, fun default_carrier_get/2).
%% @doc Extracts the current context from the provided `Carrier' using the
%% given `Propagator' and functions to get all the keys and get the keys from the carrier.
-spec extract_to(otel_ctx:t(), otel_propagator:t(), otel_propagator:carrier(), fun(), fun()) -> otel_ctx:t().
extract_to(Context, Propagator, Carrier, CarrierKeysFun, CarrierGetFun) when is_atom(Propagator) ->
Propagator:extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, []);
extract_to(Context, {Propagator, Options}, Carrier, CarrierKeysFun, CarrierGetFun) ->
Propagator:extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Options).
%% case-insensitive finding of a key string in a list of ASCII strings
%% if there are multiple entries in the list for the same key the values
%% will be combined and separated by commas. This is the method defined
%% in RFC7230 for HTTP headers.
%% @private
-spec default_carrier_get(field_key(), default_text_map_carrier()) -> field_value() | undefined.
default_carrier_get(Key, List) ->
default_carrier_get(Key, List, []).
default_carrier_get(_, [], []) ->
undefined;
default_carrier_get(_, [], Result) ->
unicode:characters_to_binary(lists:join($,, lists:reverse(Result)), latin1);
default_carrier_get(Key, [{H, V} | Rest], Result) ->
case string:equal(Key, H, true, none) of
true ->
default_carrier_get(Key, Rest, [V | Result]);
false ->
default_carrier_get(Key, Rest, Result)
end.
%% case-insensitive ASCII string based lists:keyreplace
%% @private
-spec default_carrier_set(field_key(), field_value(), default_text_map_carrier())
-> default_text_map_carrier().
default_carrier_set(Key, Value, []) ->
[{Key, Value}];
default_carrier_set(Key, Value, [{H, _}=Elem | Rest]) ->
case string:equal(Key, H, true, none) of
true ->
[{Key, Value} | Rest];
false ->
[Elem | default_carrier_set(Key, Value, Rest)]
end.
%% @private
-spec default_carrier_keys(default_text_map_carrier()) -> [field_key()].
default_carrier_keys([]) ->
[];
default_carrier_keys([{K, _} | Rest]) ->
[K | default_carrier_keys(Rest)].

View File

@ -0,0 +1,105 @@
%%%------------------------------------------------------------------------
%% Copyright 2020, OpenTelemetry Authors
%% 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.
%%
%% @doc A Composite TextMap Propagator is a Propagator that performs run
%% multiple TextMap Propagators in a specified order.
%%
%% An example of creating a Composite TextMap Propagator to inject and
%% extract Baggage and TraceContext:
%%
%% ```
%% Propagator = otel_propagator_text_map_composite:create([trace_context, baggage]),
%% otel_propagator_text_map:extract(Propagator, Carrier)
%% '''
%% @end
%%%-------------------------------------------------------------------------
-module(otel_propagator_text_map_composite).
-behaviour(otel_propagator_text_map).
-export([create/1,
fields/1,
inject/4,
extract/5,
report_cb/1]).
-include_lib("kernel/include/logger.hrl").
%% @doc Create a new Composite TextMap Propagator.
%%
%% The `Propagators' list is a list of atoms that represent the <i>suffix</i>
%% of the module name of the TextMap Propagator to be used.
-spec create([otel_propagator:builtin()]) -> otel_propagator:t().
create(Propagators) ->
{?MODULE, otel_propagator:builtins_to_modules(Propagators)}.
%% @private
fields(Propagators) ->
lists:flatmap(fun(Propagator) ->
otel_propagator_text_map:fields(Propagator)
end, Propagators).
%% @private
-spec inject(Context, Carrier, CarrierSetFun, Injectors) -> Carrier
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierSetFun :: otel_propagator_text_map:carrier_set(),
Injectors :: [otel_propagator_text_map:t()].
inject(Context, Carrier, CarrierSetFun, Injectors) ->
run_injectors(Context, Injectors, Carrier, CarrierSetFun).
%% @private
-spec extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Extractors) -> Context
when Context :: otel_ctx:t(),
Carrier :: otel_propagator:carrier(),
CarrierKeysFun :: otel_propagator_text_map:carrier_keys(),
CarrierGetFun :: otel_propagator_text_map:carrier_get(),
Extractors :: [otel_propagator_text_map:t()].
extract(Context, Carrier, CarrierKeysFun, CarrierGetFun, Extractors) ->
run_extractors(Context, Extractors, Carrier, CarrierKeysFun, CarrierGetFun).
run_extractors(Context, Extractors, Carrier, CarrierKeysFun, CarrierGetFun) when is_list(Extractors) ->
lists:foldl(fun(Propagator, ContextAcc) ->
try otel_propagator_text_map:extract_to(ContextAcc, Propagator, Carrier, CarrierKeysFun, CarrierGetFun)
catch
C:E:S ->
?LOG_INFO(#{extractor => Propagator, carrier => Carrier,
class => C, exception => E, stacktrace => S},
#{report_cb => fun ?MODULE:report_cb/1}),
ContextAcc
end
end, Context, otel_propagator:builtins_to_modules(Extractors)).
run_injectors(Context, Injectors, Carrier, Setter) when is_list(Injectors) ->
lists:foldl(fun(Propagator, CarrierAcc) ->
try otel_propagator_text_map:inject_from(Context, Propagator, CarrierAcc, Setter)
catch
C:E:S ->
?LOG_INFO(#{injector => Propagator, carrier => CarrierAcc,
class => C, exception => E, stacktrace => S},
#{report_cb => fun ?MODULE:report_cb/1}),
CarrierAcc
end
end, Carrier, otel_propagator:builtins_to_modules(Injectors)).
%% @private
report_cb(#{extractor := Propagator, carrier := _Carrier,
class := Class, exception := Exception, stacktrace := StackTrace}) ->
{"text map propagator failed to extract from carrier: propagator=~ts exception=~ts",
[Propagator, otel_utils:format_exception(Class, Exception, StackTrace)]};
report_cb(#{injector := Propagator, carrier := _Carrier,
class := Class, exception := Exception, stacktrace := StackTrace}) ->
{"text map propagator failed to inject to carrier: propagator=~ts exception=~ts",
[Propagator, otel_utils:format_exception(Class, Exception, StackTrace)]}.

Some files were not shown because too many files have changed in this diff Show More