Compare commits
294 Commits
Author | SHA1 | Date |
---|---|---|
|
4237a26517 | |
|
590f11213c | |
|
ff4d32646a | |
|
17b4065d6c | |
|
b79242d858 | |
|
dfd35c7a8d | |
|
c0855e867a | |
|
5764814b8e | |
|
42c4091802 | |
|
dc2874e2fa | |
|
352acfb24b | |
|
3e5368eba8 | |
|
80da2ab3d9 | |
|
29a7fe8f13 | |
|
887778fa0b | |
|
8e232157d1 | |
|
b185cfb94f | |
|
57580f56e5 | |
|
7781706de2 | |
|
ce1e26f579 | |
|
80094155e9 | |
|
38207b740e | |
|
c54a301e5e | |
|
804d5f3a07 | |
|
40f71ed52a | |
|
95dc35b2dd | |
|
6cac14d649 | |
|
78a917da2e | |
|
4821c37ec0 | |
|
cecfb835be | |
|
915c64a365 | |
|
de491791a4 | |
|
05f67023da | |
|
e949555a70 | |
|
d9c9583409 | |
|
15ae8c0f35 | |
|
518623882b | |
|
7768b2d106 | |
|
e0fdeb3dae | |
|
ab078e0f35 | |
|
9406936154 | |
|
85f662abfe | |
|
317c00261b | |
|
9db6f62129 | |
|
0309b30c44 | |
|
43f3f7d059 | |
|
360897b98e | |
|
6dd69e96e8 | |
|
50e3d4d949 | |
|
2c0ee00508 | |
|
a7315c63b6 | |
|
edd51d45a1 | |
|
e2e2dbbc26 | |
|
b203d2f23e | |
|
6e8a466ca4 | |
|
0ca502bddd | |
|
9329f8675e | |
|
9262a81432 | |
|
11e424de8d | |
|
aeb08f40a0 | |
|
b0a9deb7d8 | |
|
76913bb224 | |
|
55a1b57644 | |
|
bf65026b71 | |
|
fa31e52722 | |
|
ada5af60d1 | |
|
2eb84bf417 | |
|
d90cf44c87 | |
|
cc2844d867 | |
|
07f01c363f | |
|
3f73f12f83 | |
|
fe315a3a23 | |
|
f9dc916a80 | |
|
4a33b66996 | |
|
d5a2fa2bda | |
|
6a164a9a36 | |
|
67e3f7baf0 | |
|
e35ba16e55 | |
|
289bebaf15 | |
|
7a4a452603 | |
|
5a25bb6fe1 | |
|
07e8d434f3 | |
|
d37f6bd93a | |
|
e25b776840 | |
|
c34a25efd5 | |
|
d034464ffd | |
|
f2f29f5976 | |
|
8ed10f2ad7 | |
|
5e50aa7ee6 | |
|
cb92d970d4 | |
|
5fada737bf | |
|
c874197d64 | |
|
d41c099e62 | |
|
9e76c90a04 | |
|
93d9e7278f | |
|
b11316b0bd | |
|
a756317511 | |
|
3b596aae1b | |
|
d239b7017d | |
|
f7207352a1 | |
|
2c762e0be8 | |
|
dfbea872b1 | |
|
fd93c2b8c4 | |
|
ba37bf1a69 | |
|
6982730ffb | |
|
f94b056f83 | |
|
5898a425c5 | |
|
afe3440e91 | |
|
53b1f7c624 | |
|
90e030f213 | |
|
03e7f98965 | |
|
145ceaa94c | |
|
6153023d98 | |
|
04fc212451 | |
|
cc7d0855e7 | |
|
452464820a | |
|
deeceebe8d | |
|
6bd13ffcbc | |
|
3c1f556831 | |
|
4c6ba0aed1 | |
|
d698c1d326 | |
|
3219437316 | |
|
bed02d5f61 | |
|
394cd354a3 | |
|
e419b5d588 | |
|
acc64ee012 | |
|
e8305ee3f5 | |
|
983133fd0d | |
|
58acb531c5 | |
|
18548f47ad | |
|
f0f263031a | |
|
288907d349 | |
|
eec21201b1 | |
|
54e5ea7bf2 | |
|
d70fe5b029 | |
|
5bda810da8 | |
|
39ba216f00 | |
|
804714d28e | |
|
7cbcdd65b6 | |
|
4aeb2f79be | |
|
29523e62ea | |
|
3ef4be2d84 | |
|
56ae62e2d6 | |
|
2e59170339 | |
|
e2a5d20955 | |
|
33a1a9e5fe | |
|
eb14ef665e | |
|
d114161694 | |
|
8c1e348fb8 | |
|
beb5917939 | |
|
b8d9c027fd | |
|
b468a2e9bf | |
|
2460c92400 | |
|
86b7e76082 | |
|
5c4a0ad78f | |
|
8fda429ae6 | |
|
9e3f702d5b | |
|
04677f93b3 | |
|
349052c34d | |
|
9e1e9c6e9f | |
|
65472798f6 | |
|
f17b8b0414 | |
|
e392b11bbf | |
|
4e457f75a8 | |
|
d13f04d084 | |
|
14e2fefe7a | |
|
ccfcecf8fe | |
|
8a998225d0 | |
|
a01bf6cfd0 | |
|
0191a01b3b | |
|
e695b66950 | |
|
563087f0f0 | |
|
00fbeb2695 | |
|
6855cd3143 | |
|
5d3ae0199f | |
|
dc0b4acd86 | |
|
2d1c14ee56 | |
|
9cb636502e | |
|
4e243f2b63 | |
|
d7fb208d06 | |
|
1f5a560fbb | |
|
58bf4e4018 | |
|
a8493271bc | |
|
00b61a2d87 | |
|
10eda198c0 | |
|
aa17528ec1 | |
|
688e1031c6 | |
|
7f86458580 | |
|
3eb7ef00ad | |
|
f801a159f3 | |
|
b3126023db | |
|
233e111a09 | |
|
4ecc0becfd | |
|
184090914e | |
|
8fe071afee | |
|
a7e92dfe81 | |
|
dc44948c4f | |
|
a48b48fa29 | |
|
e34049b74e | |
|
1500b0f3ba | |
|
0c6a04710b | |
|
22acb3e8ec | |
|
f2f990c81d | |
|
e46742d944 | |
|
2cf5f0128b | |
|
e6f90f58ce | |
|
9698d24fdf | |
|
526137fd64 | |
|
7b732c8498 | |
|
a1fed61742 | |
|
3c12e3af1a | |
|
9e0efd4267 | |
|
cc7b268cec | |
|
3ac1f9f695 | |
|
747368a94b | |
|
000fd0f209 | |
|
9172089ab9 | |
|
9b596d03d1 | |
|
9c1b9f609f | |
|
09bac7d077 | |
|
490173b0da | |
|
0673fcfda5 | |
|
a3dd67739a | |
|
d0848e3351 | |
|
d511a28df9 | |
|
708244ec48 | |
|
9d4f61ad0b | |
|
974653fe66 | |
|
2e4f9ede58 | |
|
8efade69a1 | |
|
4d34b53e0c | |
|
0de9fc084d | |
|
1b1d537375 | |
|
42056f57c8 | |
|
b3e3fff83c | |
|
cd86405148 | |
|
33b37abe9a | |
|
0618791928 | |
|
5015698d2b | |
|
3c71b798a5 | |
|
0a993b392c | |
|
16f3637b0b | |
|
dc46ccd2c9 | |
|
d1ce438e00 | |
|
173e80b9c2 | |
|
3dd7134f81 | |
|
cd1f61725c | |
|
313d391e55 | |
|
865c89f47d | |
|
5a10b685d4 | |
|
3d3bff5bda | |
|
31f484f39f | |
|
2de5a2c484 | |
|
9f5b67b3c3 | |
|
80af8a33a0 | |
|
c91f56ece8 | |
|
f33cba3b1d | |
|
b5daeb0871 | |
|
3c77016788 | |
|
ee731aabd3 | |
|
56941a5ba6 | |
|
37969926d1 | |
|
0465c79151 | |
|
5879f48dc8 | |
|
f937eff1ee | |
|
5b93c08eed | |
|
a9d7f1ebda | |
|
d08c5030d3 | |
|
3f3b42483a | |
|
8ed2e0c79f | |
|
d69ea6c37d | |
|
ca6fa4e801 | |
|
41e54f7481 | |
|
fe73fb737a | |
|
3d3355305b | |
|
e47963612e | |
|
3e1d9536f8 | |
|
43fba2e984 | |
|
b56b10ff57 | |
|
27d863375b | |
|
c285def1d9 | |
|
8e71517fdb | |
|
768e789160 | |
|
517893e817 | |
|
c77e66475a | |
|
00f00433f3 | |
|
06449488ce | |
|
92b089ab2c | |
|
89a830cfb4 | |
|
867bb1f24e | |
|
5b1e444980 | |
|
d22baecc95 | |
|
41c51a052c | |
|
bd6b974e99 |
|
@ -0,0 +1,8 @@
|
|||
# see https://github.com/cncf/clomonitor/blob/main/docs/checks.md#exemptions
|
||||
exemptions:
|
||||
- check: artifacthub_badge
|
||||
reason: "Artifact Hub doesn't support Java packages"
|
||||
- check: signed_releases
|
||||
reason: "Maven central releases are signed and there are no GitHub release artifacts"
|
||||
- check: openssf_badge
|
||||
reason: "ETOOMANYBADGES, but the work has been done: https://www.bestpractices.dev/projects/9991"
|
|
@ -0,0 +1,40 @@
|
|||
version: 3
|
||||
|
||||
targets:
|
||||
only:
|
||||
- type: gradle
|
||||
exclude:
|
||||
# these modules are not published and so consumers will not be exposed to them
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':api:testing-internal'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':exporters:otlp:testing-internal'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':integration-tests'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':integration-tests:graal'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':integration-tests:graal-incubating'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':integration-tests:otlp'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':integration-tests:tracecontext'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':perf-harness'
|
||||
- type: gradle
|
||||
path: ./
|
||||
target: ':testing-internal'
|
||||
|
||||
experimental:
|
||||
gradle:
|
||||
configurations-only:
|
||||
# consumer will only be exposed to these dependencies
|
||||
- runtimeClasspath
|
|
@ -1,48 +1,85 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
$schema: 'https://docs.renovatebot.com/renovate-schema.json',
|
||||
extends: [
|
||||
'config:best-practices',
|
||||
'helpers:pinGitHubActionDigestsToSemver',
|
||||
],
|
||||
"packageRules": [
|
||||
packageRules: [
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"io.opentelemetry.proto:opentelemetry-proto",
|
||||
"io.opentelemetry.semconv:opentelemetry-semconv-incubating"
|
||||
// this is to reduce the number of renovate PRs
|
||||
matchManagers: [
|
||||
'github-actions',
|
||||
'dockerfile',
|
||||
],
|
||||
extends: [
|
||||
'schedule:weekly',
|
||||
],
|
||||
groupName: 'weekly update',
|
||||
},
|
||||
{
|
||||
matchPackageNames: [
|
||||
'io.opentelemetry.contrib:opentelemetry-aws-xray-propagator',
|
||||
'io.opentelemetry.proto:opentelemetry-proto',
|
||||
'io.opentelemetry.semconv:opentelemetry-semconv-incubating',
|
||||
],
|
||||
// Renovate's default behavior is only to update from unstable -> unstable if it's for the
|
||||
// major.minor.patch, under the assumption that you would want to update to the stable version
|
||||
// of that release instead of the unstable version for a future release
|
||||
// (TODO remove once the artifacts above release stable versions)
|
||||
"ignoreUnstable": false,
|
||||
"allowedVersions": "!/\\-SNAPSHOT$/"
|
||||
ignoreUnstable: false,
|
||||
allowedVersions: '!/\\-SNAPSHOT$/',
|
||||
},
|
||||
{
|
||||
// junit-pioneer 2+ requires Java 11+
|
||||
"matchPackageNames": ["org.junit-pioneer:junit-pioneer"],
|
||||
"matchUpdateTypes": ["major"],
|
||||
"enabled": false
|
||||
matchPackageNames: [
|
||||
'org.junit-pioneer:junit-pioneer',
|
||||
],
|
||||
matchUpdateTypes: [
|
||||
'major',
|
||||
],
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
// mockito 5+ requires Java 11+
|
||||
"matchPackagePrefixes": ["org.mockito:"],
|
||||
"matchUpdateTypes": ["major"],
|
||||
"enabled": false
|
||||
matchUpdateTypes: [
|
||||
'major',
|
||||
],
|
||||
enabled: false,
|
||||
matchPackageNames: [
|
||||
'org.mockito:{/,}**',
|
||||
],
|
||||
},
|
||||
{
|
||||
// jqf-fuzz version 1.8+ requires Java 11+
|
||||
"matchPackageNames": ["edu.berkeley.cs.jqf:jqf-fuzz"],
|
||||
"matchUpdateTypes": ["major", "minor"],
|
||||
"enabled": false
|
||||
matchPackageNames: [
|
||||
'edu.berkeley.cs.jqf:jqf-fuzz',
|
||||
],
|
||||
matchUpdateTypes: [
|
||||
'major',
|
||||
'minor',
|
||||
],
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
// pinned version for compatibility
|
||||
"matchPackageNames": ["org.jetbrains.kotlinx:kotlinx-coroutines-core"],
|
||||
"matchCurrentVersion": "1.5.2",
|
||||
"enabled": false
|
||||
matchPackageNames: [
|
||||
'org.jetbrains.kotlinx:kotlinx-coroutines-core',
|
||||
],
|
||||
matchCurrentVersion: '1.5.2',
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
"matchPackagePrefixes": ["com.diffplug.spotless"],
|
||||
"groupName": "spotless packages"
|
||||
groupName: 'spotless packages',
|
||||
matchPackageNames: [
|
||||
'com.diffplug.spotless{/,}**',
|
||||
],
|
||||
},
|
||||
{
|
||||
// equals verifier v4+ requires java 17+
|
||||
groupName: 'nl.jqno.equalsverifier',
|
||||
matchPackageNames: [ 'equalsverifier'],
|
||||
matchUpdateTypes: [ 'major' ],
|
||||
enabled: false
|
||||
}
|
||||
]
|
||||
],
|
||||
}
|
||||
|
|
|
@ -1,75 +1,24 @@
|
|||
# Repository settings
|
||||
|
||||
Repository settings in addition to what's documented already at
|
||||
<https://github.com/open-telemetry/community/blob/main/docs/how-to-configure-new-repository.md>.
|
||||
|
||||
## General > Pull Requests
|
||||
|
||||
* Allow squash merging > Default to pull request title
|
||||
|
||||
## Actions > General
|
||||
|
||||
* Fork pull request workflows from outside collaborators:
|
||||
"Require approval for first-time contributors who are new to GitHub"
|
||||
|
||||
(To reduce friction for new contributors,
|
||||
as the default is "Require approval for first-time contributors")
|
||||
|
||||
## Branch protections
|
||||
|
||||
The order of branch protection rules
|
||||
[can be important](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule#about-branch-protection-rules).
|
||||
The branch protection rules below should be added before the `**/**` branch protection rule
|
||||
(this may require deleting the `**/**` rule and recreating it at the end).
|
||||
|
||||
### `main`
|
||||
|
||||
* Require branches to be up to date before merging: UNCHECKED
|
||||
|
||||
(PR jobs take too long, and leaving this unchecked has not been a significant problem)
|
||||
|
||||
* Status checks that are required:
|
||||
|
||||
* EasyCLA
|
||||
* required-status-check
|
||||
|
||||
### `release/*`
|
||||
|
||||
Same settings as above for `main`, except:
|
||||
|
||||
* Restrict pushes that create matching branches: UNCHECKED
|
||||
|
||||
(So that opentelemetrybot can create release branches)
|
||||
|
||||
### `renovate/**/**`, and `opentelemetrybot/*`
|
||||
|
||||
* Require status checks to pass before merging: UNCHECKED
|
||||
|
||||
(So that renovate PRs can be rebased)
|
||||
|
||||
* Restrict who can push to matching branches: UNCHECKED
|
||||
|
||||
(So that bots can create PR branches in this repository)
|
||||
|
||||
* Allow force pushes > Everyone
|
||||
|
||||
(So that renovate PRs can be rebased)
|
||||
|
||||
* Allow deletions: CHECKED
|
||||
|
||||
(So that bot PR branches can be deleted)
|
||||
|
||||
### `benchmarks`
|
||||
|
||||
- Everything UNCHECKED
|
||||
|
||||
(This branch is currently only used for directly pushing benchmarking results from the
|
||||
[overhead benchmark](https://github.com/open-telemetry/opentelemetry-java/actions/workflows/benchmark.yml)
|
||||
job)
|
||||
This document describes any changes that have been made to the
|
||||
settings in this repository outside the settings tracked in the
|
||||
private admin repo.
|
||||
|
||||
## Secrets and variables > Actions
|
||||
|
||||
* `GPG_PASSWORD` - stored in OpenTelemetry-Java 1Password
|
||||
* `GPG_PRIVATE_KEY` - stored in OpenTelemetry-Java 1Password
|
||||
* `SONATYPE_KEY` - owned by [@jack-berg](https://github.com/jack-berg)
|
||||
* `SONATYPE_USER` - owned by [@jack-berg](https://github.com/jack-berg)
|
||||
- `GPG_PASSWORD` - stored in OpenTelemetry-Java 1Password
|
||||
- `GPG_PRIVATE_KEY` - stored in OpenTelemetry-Java 1Password
|
||||
- `NVD_API_KEY` - stored in OpenTelemetry-Java 1Password
|
||||
- Generated at https://nvd.nist.gov/developers/request-an-api-key
|
||||
- Key is associated with [@trask](https://github.com/trask)'s gmail address
|
||||
- `SONATYPE_KEY` - owned by [@jack-berg](https://github.com/jack-berg)
|
||||
- `SONATYPE_USER` - owned by [@jack-berg](https://github.com/jack-berg)
|
||||
|
||||
### Organization secrets
|
||||
|
||||
- `FOSSA_API_KEY`
|
||||
- `OTELBOT_PRIVATE_KEY`
|
||||
|
||||
### Organization variables
|
||||
|
||||
- `OTELBOT_APP_ID`
|
||||
|
|
|
@ -86,5 +86,5 @@ echo $contributors1 $contributors2 \
|
|||
| grep -v github-actions \
|
||||
| grep -v renovate \
|
||||
| grep -v codecov \
|
||||
| grep -v opentelemetrybot \
|
||||
| grep -v otelbot \
|
||||
| sed 's/^/@/'
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
version=$1
|
||||
versionWithSnapshot="$version-SNAPSHOT"
|
||||
|
||||
sed -Ei "s/[0-9]+\.[0-9]+\.[0-9]+/$version/" version.gradle.kts
|
||||
|
||||
sed -Ei "1 s/(Comparing source compatibility of [a-z-]+)-[0-9]+\.[0-9]+\.[0-9]+(-SNAPSHOT)?.jar/\1-$versionWithSnapshot.jar/" docs/apidiffs/current_vs_latest/*.txt
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
git config user.name opentelemetrybot
|
||||
git config user.email 107717825+opentelemetrybot@users.noreply.github.com
|
||||
git config user.name otelbot
|
||||
git config user.email 197425009+otelbot@users.noreply.github.com
|
||||
|
|
|
@ -6,8 +6,13 @@ on:
|
|||
description: "The pull request # to backport"
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
permissions:
|
||||
contents: write # for git push to PR branch
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
|
@ -16,7 +21,7 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
# history is needed to run git cherry-pick below
|
||||
fetch-depth: 0
|
||||
|
@ -24,16 +29,22 @@ jobs:
|
|||
- name: Use CLA approved github bot
|
||||
run: .github/scripts/use-cla-approved-github-bot.sh
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
id: otelbot-token
|
||||
with:
|
||||
app-id: ${{ vars.OTELBOT_APP_ID }}
|
||||
private-key: ${{ secrets.OTELBOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Create pull request
|
||||
env:
|
||||
NUMBER: ${{ github.event.inputs.number }}
|
||||
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
|
||||
GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
|
||||
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
|
||||
run: |
|
||||
commit=$(gh pr view $NUMBER --json mergeCommit --jq .mergeCommit.oid)
|
||||
title=$(gh pr view $NUMBER --json title --jq .title)
|
||||
|
||||
branch="opentelemetrybot/backport-${NUMBER}-to-${GITHUB_REF_NAME//\//-}"
|
||||
branch="otelbot/backport-${NUMBER}-to-${GITHUB_REF_NAME//\//-}"
|
||||
|
||||
git checkout -b $branch
|
||||
git cherry-pick $commit
|
||||
|
|
|
@ -3,10 +3,15 @@ name: Benchmark Tags
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sdk-benchmark:
|
||||
permissions:
|
||||
contents: write # for git push to benchmarks branch
|
||||
name: Benchmark SDK
|
||||
runs-on: self-hosted
|
||||
runs-on: equinix-bare-metal
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -39,19 +44,19 @@ jobs:
|
|||
- v1.30.0
|
||||
- v1.30.1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ matrix.tag-version }}
|
||||
|
||||
- id: setup-java
|
||||
name: Set up Java for build
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
- name: Run jmh
|
||||
run: ./gradlew jmhJar
|
||||
|
||||
|
@ -61,7 +66,7 @@ jobs:
|
|||
java -jar libs/opentelemetry-sdk-trace-*-jmh.jar -rf json SpanBenchmark SpanPipelineBenchmark ExporterBenchmark
|
||||
|
||||
- name: Store benchmark results
|
||||
uses: benchmark-action/github-action-benchmark@v1
|
||||
uses: benchmark-action/github-action-benchmark@d48d326b4ca9ba73ca0cd0d59f108f9e02a381c7 # v1.20.4
|
||||
with:
|
||||
tool: 'jmh'
|
||||
output-file-path: sdk/trace/build/jmh-result.json
|
||||
|
|
|
@ -5,23 +5,28 @@ on:
|
|||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sdk-benchmark:
|
||||
permissions:
|
||||
contents: write # for git push to benchmarks branch
|
||||
name: Benchmark SDK
|
||||
runs-on: self-hosted
|
||||
runs-on: equinix-bare-metal
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- id: setup-java
|
||||
name: Set up Java for build
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
- name: Run jmh
|
||||
run: ./gradlew jmhJar
|
||||
|
||||
|
@ -31,7 +36,7 @@ jobs:
|
|||
java -jar libs/opentelemetry-sdk-trace-*-jmh.jar -rf json SpanBenchmark SpanPipelineBenchmark ExporterBenchmark
|
||||
|
||||
- name: Store benchmark results
|
||||
uses: benchmark-action/github-action-benchmark@v1
|
||||
uses: benchmark-action/github-action-benchmark@d48d326b4ca9ba73ca0cd0d59f108f9e02a381c7 # v1.20.4
|
||||
with:
|
||||
tool: 'jmh'
|
||||
output-file-path: sdk/trace/build/jmh-result.json
|
||||
|
|
|
@ -9,21 +9,27 @@ on:
|
|||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to GitHub package registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||
with:
|
||||
context: integration-tests/tracecontext/docker
|
||||
push: true
|
||||
|
|
|
@ -12,6 +12,9 @@ concurrency:
|
|||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
|
@ -32,7 +35,7 @@ jobs:
|
|||
- 23
|
||||
# Collect coverage on latest LTS
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-latest
|
||||
test-java-version: 21
|
||||
coverage: true
|
||||
jmh-based-tests: true
|
||||
|
@ -49,24 +52,24 @@ jobs:
|
|||
- os: macos-13
|
||||
test-java-version: 23
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- id: setup-java-test
|
||||
name: Set up Java ${{ matrix.test-java-version }} for tests
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: ${{ matrix.test-java-version }}
|
||||
|
||||
- id: setup-java
|
||||
name: Set up Java for build
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
- name: Build
|
||||
run: >
|
||||
./gradlew build
|
||||
|
@ -79,10 +82,10 @@ jobs:
|
|||
RUN_JMH_BASED_TESTS: ${{ matrix.jmh-based-tests }}
|
||||
|
||||
- name: Check for diff
|
||||
# The jApiCmp diff compares current to latest, which isn't appropriate for release branches, or for bot-generated PRs
|
||||
# The jApiCmp diff compares current to latest, which isn't appropriate for release branches
|
||||
# this fails on windows because of the bash-specific if/then/else syntax, but that's ok
|
||||
# because we only need to run this validation once (on any platform)
|
||||
if: ${{ matrix.os != 'windows-latest' && !startsWith(github.ref_name, 'release/') && !startsWith(github.base_ref, 'release/') && (github.actor != 'opentelemetrybot') }}
|
||||
if: ${{ matrix.os != 'windows-latest' && !startsWith(github.ref_name, 'release/') && !startsWith(github.base_ref, 'release/') }}
|
||||
run: |
|
||||
# need to "git add" in case any generated files did not already exist
|
||||
git add docs/apidiffs
|
||||
|
@ -96,12 +99,12 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
- uses: codecov/codecov-action@v5
|
||||
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
if: ${{ matrix.coverage }}
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
if: ${{ matrix.coverage }}
|
||||
with:
|
||||
name: coverage-report
|
||||
|
@ -132,17 +135,17 @@ jobs:
|
|||
needs: build
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- id: setup-java
|
||||
name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
# skipping release branches because the versions in those branches are not snapshots
|
||||
# (also this skips pull requests)
|
||||
if: ${{ github.ref_name == 'main' && github.repository == 'open-telemetry/opentelemetry-java' }}
|
||||
|
@ -158,13 +161,19 @@ jobs:
|
|||
GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
|
||||
|
||||
build-graal:
|
||||
name: Build GraalVM
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
test-graal-version:
|
||||
- 21
|
||||
- 23
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: graalvm/setup-graalvm@v1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5
|
||||
with:
|
||||
# TODO(jack-berg): Which versions do we need to test? Should we use a matrix scheme?
|
||||
java-version: '21'
|
||||
java-version: ${{ matrix.test-graal-version }}
|
||||
distribution: 'graalvm'
|
||||
components: 'native-image'
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
name: CodeQL (daily)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Daily at 01:30 (UTC)
|
||||
- cron: '30 1 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Java 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: java
|
||||
# using "latest" helps to keep up with the latest Kotlin support
|
||||
# see https://github.com/github/codeql-action/issues/1555#issuecomment-1452228433
|
||||
tools: latest
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Assemble
|
||||
# skipping build cache is needed so that all modules will be analyzed
|
||||
run: ./gradlew assemble --no-build-cache
|
||||
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
open-issue-on-failure:
|
||||
# open an issue on failure because it can be easy to miss CI failure notifications
|
||||
needs:
|
||||
- analyze
|
||||
if: failure() && github.run_attempt == 1
|
||||
uses: ./.github/workflows/reusable-open-issue-on-failure.yml
|
|
@ -0,0 +1,65 @@
|
|||
name: CodeQL
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- release/*
|
||||
- benchmarks
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release/*
|
||||
- benchmarks
|
||||
schedule:
|
||||
- cron: "23 16 * * 2" # weekly at 16:23 UTC on Tuesday
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read # for github/codeql-action/init to get workflow details
|
||||
security-events: write # for github/codeql-action/analyze to upload SARIF results
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
- language: java
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Java 17
|
||||
if: matrix.language == 'java'
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
if: matrix.language == 'java'
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# using "latest" helps to keep up with the latest Kotlin support
|
||||
# see https://github.com/github/codeql-action/issues/1555#issuecomment-1452228433
|
||||
tools: latest
|
||||
|
||||
- name: Assemble
|
||||
if: matrix.language == 'java'
|
||||
# --no-build-cache is required for codeql to analyze all modules
|
||||
# --no-daemon is required for codeql to observe the compilation
|
||||
# (see https://docs.github.com/en/code-security/codeql-cli/getting-started-with-the-codeql-cli/preparing-your-code-for-codeql-analysis#specifying-build-commands)
|
||||
run: ./gradlew assemble --no-build-cache --no-daemon
|
||||
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
|
@ -5,8 +5,14 @@ on:
|
|||
- cron: "23 3 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
copy-images:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
|
@ -21,7 +27,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Docker login
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
name: FOSSA
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
fossa:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
|
||||
with:
|
||||
api-key: ${{secrets.FOSSA_API_KEY}}
|
||||
team: OpenTelemetry
|
|
@ -1,69 +0,0 @@
|
|||
name: Generate Post-Release PR
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
prereqs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Verify prerequisites
|
||||
run: |
|
||||
if [[ $GITHUB_REF_NAME != main ]]; then
|
||||
echo this workflow should only be run against main
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create-pull-request-against-main:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prereqs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: setup-java
|
||||
name: Set up Java for build
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set environment variables
|
||||
run: |
|
||||
version=$(.github/scripts/get-version.sh)
|
||||
echo "VERSION=$version" >> $GITHUB_ENV
|
||||
prior_version=$(.github/scripts/get-prior-version.sh)
|
||||
echo "PRIOR_VERSION=$prior_version" >> $GITHUB_ENV
|
||||
if [[ $prior_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
|
||||
major="${BASH_REMATCH[1]}"
|
||||
minor="${BASH_REMATCH[2]}"
|
||||
patch="${BASH_REMATCH[3]}"
|
||||
|
||||
two_releases_ago="$major.$((minor - 1)).$patch"
|
||||
else
|
||||
echo "unexpected prior version: $prior_version"
|
||||
exit 1
|
||||
fi
|
||||
echo "TWO_VERSIONS_AGO=$two_releases_ago" >> $GITHUB_ENV
|
||||
- name: Use CLA approved github bot
|
||||
run: .github/scripts/use-cla-approved-github-bot.sh
|
||||
|
||||
- name: Create pull request against main
|
||||
env:
|
||||
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
|
||||
GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
|
||||
run: |
|
||||
./gradlew updateVersionInDocs -Prelease.version=$PRIOR_VERSION
|
||||
./gradlew japicmp -PapiBaseVersion=$TWO_VERSIONS_AGO -PapiNewVersion=$PRIOR_VERSION
|
||||
./gradlew --refresh-dependencies japicmp
|
||||
|
||||
message="Post release for version $PRIOR_VERSION"
|
||||
body="Post-release updates for version \`$PRIOR_VERSION\`."
|
||||
branch="opentelemetrybot/post-release-for-${PRIOR_VERSION}"
|
||||
|
||||
git checkout -b $branch
|
||||
git add docs/apidiffs
|
||||
git commit -a -m "$message"
|
||||
git push --set-upstream origin $branch
|
||||
gh pr create --title "$message" \
|
||||
--body "$body" \
|
||||
--base main
|
|
@ -1,16 +1,16 @@
|
|||
name: Gradle wrapper validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**/gradle/wrapper/**'
|
||||
push:
|
||||
paths:
|
||||
- '**/gradle/wrapper/**'
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
gradle-wrapper-validation:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: gradle/actions/wrapper-validation@v4.3.0
|
||||
- uses: gradle/actions/wrapper-validation@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
|
|
@ -4,14 +4,21 @@ on:
|
|||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
issue_comment:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'needs author feedback') &&
|
||||
github.event.comment.user.login == github.event.issue.user.login
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Remove label
|
||||
env:
|
||||
|
|
|
@ -5,11 +5,18 @@ on:
|
|||
# hourly at minute 23
|
||||
- cron: "23 * * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write # for actions/stale to close stale issues
|
||||
pull-requests: write # for actions/stale to close stale PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 7
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
name: Javadoc.io site crawler (daily)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *" # daily at 1:30 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
crawl:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Run crawler
|
||||
run: ./gradlew :javadoc-crawler:crawl
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
- uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
@ -33,7 +33,7 @@ jobs:
|
|||
# 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@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
|
@ -42,6 +42,6 @@ jobs:
|
|||
# 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@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
|
||||
uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
@ -4,28 +4,44 @@ name: OWASP dependency check (daily)
|
|||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
- cron: "30 1 * * *" # daily at 1:30 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Check dependencies
|
||||
run: ./gradlew dependencyCheckAnalyze
|
||||
env:
|
||||
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
path: javaagent/build/reports
|
||||
|
||||
workflow-notification:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
needs:
|
||||
- analyze
|
||||
if: always()
|
||||
uses: ./.github/workflows/reusable-workflow-notification.yml
|
||||
with:
|
||||
success: ${{ needs.analyze.result == 'success' }}
|
||||
|
|
|
@ -2,11 +2,16 @@ name: Prepare patch release
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
prepare-patch-release:
|
||||
permissions:
|
||||
contents: write # for git push to PR branch
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- run: |
|
||||
if [[ ! $GITHUB_REF_NAME =~ ^release/v[0-9]+\.[0-9]+\.x$ ]]; then
|
||||
|
@ -32,7 +37,7 @@ jobs:
|
|||
echo "VERSION=$major_minor.$((patch + 1))" >> $GITHUB_ENV
|
||||
|
||||
- name: Update version
|
||||
run: sed -Ei "s/[0-9]+\.[0-9]+\.[0-9]+/$VERSION/" version.gradle.kts
|
||||
run: .github/scripts/update-version.sh $VERSION
|
||||
|
||||
- name: Update the change log with the approximate release date
|
||||
run: |
|
||||
|
@ -42,13 +47,19 @@ jobs:
|
|||
- name: Use CLA approved github bot
|
||||
run: .github/scripts/use-cla-approved-github-bot.sh
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
id: otelbot-token
|
||||
with:
|
||||
app-id: ${{ vars.OTELBOT_APP_ID }}
|
||||
private-key: ${{ secrets.OTELBOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Create pull request
|
||||
env:
|
||||
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
|
||||
GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
|
||||
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
|
||||
run: |
|
||||
message="Prepare release $VERSION"
|
||||
branch="opentelemetrybot/prepare-release-${VERSION}"
|
||||
branch="otelbot/prepare-release-${VERSION}"
|
||||
|
||||
git checkout -b $branch
|
||||
git commit -a -m "$message"
|
||||
|
|
|
@ -2,11 +2,14 @@ name: Prepare release branch
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
prereqs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Verify prerequisites
|
||||
run: |
|
||||
|
@ -21,11 +24,13 @@ jobs:
|
|||
fi
|
||||
|
||||
create-pull-request-against-release-branch:
|
||||
permissions:
|
||||
contents: write # for git push to PR branch
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prereqs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Create release branch
|
||||
run: |
|
||||
|
@ -54,13 +59,19 @@ jobs:
|
|||
- name: Use CLA approved github bot
|
||||
run: .github/scripts/use-cla-approved-github-bot.sh
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
id: otelbot-token
|
||||
with:
|
||||
app-id: ${{ vars.OTELBOT_APP_ID }}
|
||||
private-key: ${{ secrets.OTELBOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Create pull request against the release branch
|
||||
env:
|
||||
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
|
||||
GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
|
||||
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
|
||||
run: |
|
||||
message="Prepare release $VERSION"
|
||||
branch="opentelemetrybot/prepare-release-${VERSION}"
|
||||
branch="otelbot/prepare-release-${VERSION}"
|
||||
|
||||
git checkout -b $branch
|
||||
git commit -a -m "$message"
|
||||
|
@ -70,11 +81,13 @@ jobs:
|
|||
--base $RELEASE_BRANCH_NAME
|
||||
|
||||
create-pull-request-against-main:
|
||||
permissions:
|
||||
contents: write # for git push to PR branch
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prereqs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set environment variables
|
||||
run: |
|
||||
|
@ -87,11 +100,11 @@ jobs:
|
|||
echo "unexpected version: $version"
|
||||
exit 1
|
||||
fi
|
||||
echo "NEXT_VERSION=$next_version" >> $GITHUB_ENV
|
||||
echo "NEXT_VERSION=${next_version}" >> $GITHUB_ENV
|
||||
echo "VERSION=$version" >> $GITHUB_ENV
|
||||
|
||||
- name: Update version
|
||||
run: sed -Ei "s/[0-9]+\.[0-9]+\.[0-9]+/$NEXT_VERSION/" version.gradle.kts
|
||||
run: .github/scripts/update-version.sh $NEXT_VERSION
|
||||
|
||||
- name: Update the change log on main
|
||||
run: |
|
||||
|
@ -102,14 +115,20 @@ jobs:
|
|||
- name: Use CLA approved github bot
|
||||
run: .github/scripts/use-cla-approved-github-bot.sh
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
id: otelbot-token
|
||||
with:
|
||||
app-id: ${{ vars.OTELBOT_APP_ID }}
|
||||
private-key: ${{ secrets.OTELBOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Create pull request against main
|
||||
env:
|
||||
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
|
||||
GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
|
||||
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
|
||||
run: |
|
||||
message="Update version to $NEXT_VERSION"
|
||||
body="Update version to \`$NEXT_VERSION\`."
|
||||
branch="opentelemetrybot/update-version-to-${NEXT_VERSION}"
|
||||
branch="otelbot/update-version-to-${NEXT_VERSION}"
|
||||
|
||||
git checkout -b $branch
|
||||
git commit -a -m "$message"
|
||||
|
|
|
@ -2,11 +2,17 @@ name: Release
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
permissions:
|
||||
contents: write # for creating the release
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
version: ${{ steps.create-github-release.outputs.version }}
|
||||
prior-version: ${{ steps.create-github-release.outputs.prior-version }}
|
||||
steps:
|
||||
- run: |
|
||||
if [[ $GITHUB_REF_NAME != release/* ]]; then
|
||||
|
@ -14,15 +20,15 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Build and publish artifacts
|
||||
run: ./gradlew assemble publishToSonatype closeAndReleaseSonatypeStagingRepository
|
||||
|
@ -59,7 +65,7 @@ jobs:
|
|||
|
||||
# check out main branch to verify there won't be problems with merging the change log
|
||||
# at the end of this workflow
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: main
|
||||
|
||||
|
@ -74,7 +80,7 @@ jobs:
|
|||
fi
|
||||
|
||||
# back to the release branch
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
# tags are needed for the generate-release-contributors.sh script
|
||||
fetch-depth: 0
|
||||
|
@ -123,14 +129,20 @@ jobs:
|
|||
--notes-file /tmp/release-notes.txt \
|
||||
v$VERSION
|
||||
|
||||
# these are used as job outputs
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "prior-version=$PRIOR_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
merge-change-log-to-main:
|
||||
update-apidiff-baseline-and-docs-to-released-version:
|
||||
permissions:
|
||||
contents: write # for git push to PR branch
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# add change log sync (if any) into this PR since the apidiff update
|
||||
# is required before any other PR can be merged anyway
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Copy change log section from release branch
|
||||
env:
|
||||
|
@ -139,7 +151,7 @@ jobs:
|
|||
sed -n "0,/^## Version $VERSION /d;/^## Version /q;p" CHANGELOG.md \
|
||||
> /tmp/changelog-section.md
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: main
|
||||
|
||||
|
@ -150,32 +162,59 @@ jobs:
|
|||
run: |
|
||||
release_date=$(gh release view v$VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//')
|
||||
RELEASE_DATE=$release_date .github/scripts/merge-change-log-after-release.sh
|
||||
git add CHANGELOG.md
|
||||
|
||||
- name: Use CLA approved github bot
|
||||
- name: Wait for release to be available in maven central
|
||||
env:
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
run: |
|
||||
until curl --silent \
|
||||
--show-error \
|
||||
--output /dev/null \
|
||||
--head \
|
||||
--fail \
|
||||
https://repo1.maven.org/maven2/io/opentelemetry/opentelemetry-api/$VERSION/opentelemetry-api-$VERSION.jar
|
||||
do
|
||||
sleep 60
|
||||
done
|
||||
|
||||
- name: Update apidiff baseline
|
||||
env:
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
PRIOR_VERSION: ${{ needs.release.outputs.prior-version }}
|
||||
run: |
|
||||
./gradlew japicmp -PapiBaseVersion=$PRIOR_VERSION -PapiNewVersion=$VERSION
|
||||
./gradlew --refresh-dependencies japicmp
|
||||
git add docs/apidiffs
|
||||
|
||||
- name: Update versions in README.md
|
||||
env:
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
run: |
|
||||
./gradlew updateVersionInDocs -Prelease.version=$VERSION
|
||||
git add README.md
|
||||
|
||||
- name: Use CLA approved bot
|
||||
run: .github/scripts/use-cla-approved-github-bot.sh
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
id: otelbot-token
|
||||
with:
|
||||
app-id: ${{ vars.OTELBOT_APP_ID }}
|
||||
private-key: ${{ secrets.OTELBOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Create pull request against main
|
||||
env:
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
|
||||
GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
|
||||
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
if [[ $VERSION =~ ^[0-9]+\.[0-9]+\.0 ]]; then
|
||||
echo there are no updates to merge, not creating pull request
|
||||
exit 0 # success
|
||||
else
|
||||
echo patch release notes did not get applied for some reason
|
||||
exit 1 # failure
|
||||
fi
|
||||
fi
|
||||
|
||||
message="Merge change log updates from $GITHUB_REF_NAME"
|
||||
body="Merge log updates from \`$GITHUB_REF_NAME\`."
|
||||
branch="opentelemetrybot/merge-change-log-updates-from-${GITHUB_REF_NAME//\//-}"
|
||||
message="Update apidiff baseline and documentation versions to released version $VERSION"
|
||||
body="Update apidiff baseline and documentation versions to released version \`$VERSION\`."
|
||||
branch="otelbot/update-apidiff-baseline-and-documentation-to-released-version-${VERSION}"
|
||||
|
||||
git checkout -b $branch
|
||||
git commit -a -m "$message"
|
||||
git commit -m "$message"
|
||||
git push --set-upstream origin $branch
|
||||
gh pr create --title "$message" \
|
||||
--body "$body" \
|
||||
|
|
|
@ -3,17 +3,22 @@ name: Reusable - Markdown link check
|
|||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
markdown-link-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: lycheeverse/lychee-action@v2
|
||||
- uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2.4.1
|
||||
with:
|
||||
# excluding links to pull requests and issues is done for performance
|
||||
args: >
|
||||
--include-fragments
|
||||
--exclude "^https://github.com/open-telemetry/opentelemetry-java/(issue|pull)/\\d+$"
|
||||
--exclude "^https://github.com/open-telemetry/opentelemetry-java/(issues|pull)/\\d+$"
|
||||
--max-retries 6
|
||||
--retry-wait-time 10
|
||||
--max-concurrency 1
|
||||
.
|
||||
|
|
|
@ -3,11 +3,14 @@ name: Reusable - Misspell check
|
|||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
misspell-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Install misspell
|
||||
run: |
|
||||
|
|
|
@ -3,11 +3,17 @@ name: Reusable - Open issue on workflow failure
|
|||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
open-issue:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write # for creating the issue
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Open issue
|
||||
env:
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# this is useful because notifications for scheduled workflows are only sent to the user who
|
||||
# initially created the given workflow
|
||||
name: Reusable - Workflow notification
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
success:
|
||||
type: boolean
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
workflow-notification:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Open issue or add comment if issue already open
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# TODO (trask) search doesn't support exact phrases, so it's possible that this could grab the wrong issue
|
||||
number=$(gh issue list --search "in:title Workflow failed: $GITHUB_WORKFLOW" --limit 1 --json number -q .[].number)
|
||||
|
||||
echo $number
|
||||
echo ${{ inputs.success }}
|
||||
|
||||
if [[ $number ]]; then
|
||||
if [[ "${{ inputs.success }}" == "true" ]]; then
|
||||
gh issue close $number
|
||||
else
|
||||
gh issue comment $number \
|
||||
--body "See [$GITHUB_WORKFLOW #$GITHUB_RUN_NUMBER](https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)."
|
||||
fi
|
||||
elif [[ "${{ inputs.success }}" == "false" ]]; then
|
||||
gh issue create --title "Workflow failed: $GITHUB_WORKFLOW (#$GITHUB_RUN_NUMBER)" \
|
||||
--body "See [$GITHUB_WORKFLOW #$GITHUB_RUN_NUMBER](https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)."
|
||||
fi
|
236
CHANGELOG.md
236
CHANGELOG.md
|
@ -2,6 +2,240 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
## Version 1.52.0 (2025-07-11)
|
||||
|
||||
### API
|
||||
|
||||
#### Common
|
||||
|
||||
* Promote `ComponentLoader` to new `opentelemetry-common` artifact,
|
||||
standardize SPI loading
|
||||
([#7446](https://github.com/open-telemetry/opentelemetry-java/pull/7446))
|
||||
|
||||
#### Context
|
||||
|
||||
* LazyStorage passes its ClassLoader when loading ContextStorageProvider SPI
|
||||
([#7424](https://github.com/open-telemetry/opentelemetry-java/pull/7424))
|
||||
|
||||
#### Incubator
|
||||
|
||||
* Add context and severity params to ExtendedLogger#isEnabled
|
||||
([#7268](https://github.com/open-telemetry/opentelemetry-java/pull/7268))
|
||||
* Add new convenience methods for converting DeclarativeConfigProperties to config model
|
||||
([#7453](https://github.com/open-telemetry/opentelemetry-java/pull/7453))
|
||||
|
||||
### SDK
|
||||
|
||||
* Add custom stacktrace renderer which is length limit aware
|
||||
([#7281](https://github.com/open-telemetry/opentelemetry-java/pull/7281))
|
||||
|
||||
#### Metrics
|
||||
|
||||
* Propagate flush to PeriodicMetricReader's metricExporter.
|
||||
([#7410](https://github.com/open-telemetry/opentelemetry-java/pull/7410))
|
||||
|
||||
#### Exporters
|
||||
|
||||
* OTLP - JdkHttpSender: ensure proper closure of HttpClient in shutdown method
|
||||
([#7390](https://github.com/open-telemetry/opentelemetry-java/pull/7390))
|
||||
* OTLP: profile exporters fix and test improvements
|
||||
([#7442](https://github.com/open-telemetry/opentelemetry-java/pull/7442))
|
||||
* OTLP: Loading Compressor SPI via ComponentLoader configured through setComponentLoader
|
||||
([#7428](https://github.com/open-telemetry/opentelemetry-java/pull/7428))
|
||||
* Prometheus: add scope schema URL and attributes
|
||||
([#7356](https://github.com/open-telemetry/opentelemetry-java/pull/7356))
|
||||
* Prometheus: extend prometheus declarative config support to include without_scope_info,
|
||||
with_resource_constant_labels
|
||||
([#6840](https://github.com/open-telemetry/opentelemetry-java/pull/6840))
|
||||
|
||||
#### Extensions
|
||||
|
||||
* Autoconfigure: fix race condition of `GlobalOpenTelemetry` initialization with
|
||||
`AutoConfiguredOpenTelemetrySdkBuilder`
|
||||
([#7365](https://github.com/open-telemetry/opentelemetry-java/pull/7365))
|
||||
* Declarative config: update to declarative config 1.0-rc.1
|
||||
([#7436](https://github.com/open-telemetry/opentelemetry-java/pull/7436))
|
||||
* Declarative config: resolve environment variable substitution for mixed quotes
|
||||
([#7433](https://github.com/open-telemetry/opentelemetry-java/pull/7433))
|
||||
|
||||
## Version 1.51.0 (2025-06-06)
|
||||
|
||||
### API
|
||||
|
||||
#### Context
|
||||
|
||||
* Fix context storage provider property name in log message
|
||||
([#7342](https://github.com/open-telemetry/opentelemetry-java/pull/7342))
|
||||
|
||||
### SDK
|
||||
|
||||
* Experimental configurable exception.* attribute resolution for SdkTracerProvider,
|
||||
SdkLoggerProvider
|
||||
([#7266](https://github.com/open-telemetry/opentelemetry-java/pull/7266))
|
||||
|
||||
#### Exporters
|
||||
|
||||
* All exporters: implement new SemConv exporter health metrics, with configuration API for selecting
|
||||
schema version
|
||||
([#7265](https://github.com/open-telemetry/opentelemetry-java/pull/7265))
|
||||
* OTLP: Add gRPC export for profiles signal type.
|
||||
([#7301](https://github.com/open-telemetry/opentelemetry-java/pull/7301))
|
||||
* OTLP: Run JDK HTTP sender on non-daemon threads.
|
||||
([#7322](https://github.com/open-telemetry/opentelemetry-java/pull/7322))
|
||||
* Prometheus: fix serialization of arrays
|
||||
([#7291](https://github.com/open-telemetry/opentelemetry-java/pull/7291))
|
||||
* OTLP: exporter tolerates instances of LogRecordData when incubator is present
|
||||
([#7393](https://github.com/open-telemetry/opentelemetry-java/pull/7393))
|
||||
|
||||
#### Extensions
|
||||
|
||||
* Declarative config: Handle instrumentation node changes in yaml config file format 0.4
|
||||
([#7357](https://github.com/open-telemetry/opentelemetry-java/pull/7357))
|
||||
|
||||
## Version 1.50.0 (2025-05-09)
|
||||
|
||||
### API
|
||||
|
||||
* Clarify that AttributesBuilder.put allows nulls
|
||||
([#7271](https://github.com/open-telemetry/opentelemetry-java/pull/7271))
|
||||
* Stabilize log record event name
|
||||
([#7277](https://github.com/open-telemetry/opentelemetry-java/pull/7277))
|
||||
|
||||
#### Context
|
||||
|
||||
* Fix duplicated ExecutorService wrap
|
||||
([#7245](https://github.com/open-telemetry/opentelemetry-java/pull/7245))
|
||||
* Promote getAll to TextMapGetter stable API
|
||||
([#7267](https://github.com/open-telemetry/opentelemetry-java/pull/7267))
|
||||
|
||||
#### Incubator
|
||||
|
||||
* Add ExtendedLogRecordBuilder#setException
|
||||
([#7182](https://github.com/open-telemetry/opentelemetry-java/pull/7182))
|
||||
* Add experimental support for log extended attributes
|
||||
([#7123](https://github.com/open-telemetry/opentelemetry-java/pull/7123))
|
||||
|
||||
### SDK
|
||||
|
||||
* Remove Java9VersionSpecific clock implementation
|
||||
([#7221](https://github.com/open-telemetry/opentelemetry-java/pull/7221))
|
||||
* Add addProcessorFirst to SdkTracerProviderBuilder, SdkLoggerProviderBuilder
|
||||
([#7243](https://github.com/open-telemetry/opentelemetry-java/pull/7243))
|
||||
|
||||
#### Logs
|
||||
|
||||
* Add `setLoggerConfigurator` support to `LoggerProvider`
|
||||
([#7332](https://github.com/open-telemetry/opentelemetry-java/pull/7332))
|
||||
|
||||
#### Metrics
|
||||
|
||||
* Add DelegatingMetricData
|
||||
([#7229](https://github.com/open-telemetry/opentelemetry-java/pull/7229))
|
||||
* Spatial aggregation for async instruments with filtering views
|
||||
([#7264](https://github.com/open-telemetry/opentelemetry-java/pull/7264))
|
||||
|
||||
#### Exporters
|
||||
|
||||
* Prometheus: Add Authenticator support for PrometheusHttpServer
|
||||
([#7225](https://github.com/open-telemetry/opentelemetry-java/pull/7225))
|
||||
* OTLP: Fix OTLP metric exporter toBuilder() loosing temporality
|
||||
([#7280](https://github.com/open-telemetry/opentelemetry-java/pull/7280))
|
||||
* OTLP: Allow Otlp*MetricExporter's to publish export stats
|
||||
([#7255](https://github.com/open-telemetry/opentelemetry-java/pull/7255))
|
||||
|
||||
#### Extensions
|
||||
|
||||
* Declarative config: Add support for escaping env var substitution
|
||||
([#7033](https://github.com/open-telemetry/opentelemetry-java/pull/7033))
|
||||
* Declarative config: update to opentelemetry-configuration 0.4
|
||||
([#7064](https://github.com/open-telemetry/opentelemetry-java/pull/7064))
|
||||
* Declarativeconfig: Refactor internals to add DeclarativeConfigContext
|
||||
([#7293](https://github.com/open-telemetry/opentelemetry-java/pull/7293))
|
||||
|
||||
### Project tooling
|
||||
|
||||
* Kotlin extension: Update min kotlin version to 1.8
|
||||
([#7155](https://github.com/open-telemetry/opentelemetry-java/pull/7155))
|
||||
* Add javadoc site crawler
|
||||
([#7300](https://github.com/open-telemetry/opentelemetry-java/pull/7300),
|
||||
[#7316](https://github.com/open-telemetry/opentelemetry-java/pull/7316))
|
||||
|
||||
## Version 1.49.0 (2025-04-04)
|
||||
|
||||
### SDK
|
||||
|
||||
#### Trace
|
||||
|
||||
* Avoid linear queue.size() calls in span producers by storing queue size separately
|
||||
([#7141](https://github.com/open-telemetry/opentelemetry-java/pull/7141))
|
||||
|
||||
#### Exporters
|
||||
|
||||
* OTLP: Add support for setting exporter executor service
|
||||
([#7152](https://github.com/open-telemetry/opentelemetry-java/pull/7152))
|
||||
* OTLP: Refine delay jitter for exponential backoff
|
||||
([#7206](https://github.com/open-telemetry/opentelemetry-java/pull/7206))
|
||||
|
||||
#### Extensions
|
||||
|
||||
* Autoconfigure: Remove support for otel.experimental.exporter.otlp.retry.enabled
|
||||
([#7200](https://github.com/open-telemetry/opentelemetry-java/pull/7200))
|
||||
* Autoconfigure: Add stable cardinality limit property otel.java.metrics.cardinality.limit
|
||||
([#7199](https://github.com/open-telemetry/opentelemetry-java/pull/7199))
|
||||
* Incubator: Add declarative config model customizer SPI
|
||||
([#7118](https://github.com/open-telemetry/opentelemetry-java/pull/7118))
|
||||
|
||||
## Version 1.48.0 (2025-03-07)
|
||||
|
||||
### API
|
||||
|
||||
* Add some helpful logging attribute methods to `LogRecordBuilder`
|
||||
([#7089](https://github.com/open-telemetry/opentelemetry-java/pull/7089))
|
||||
|
||||
#### Incubator
|
||||
|
||||
* Introduce ConfigProvider API. Rename `StructuredConfigProperties` to `DeclarativeConfigProperties`
|
||||
and move to `opentelemetry-api-incubator`. Rename `FileConfiguration`
|
||||
to `DeclarativeConfiguration`.
|
||||
([#6549](https://github.com/open-telemetry/opentelemetry-java/pull/6549))
|
||||
|
||||
### SDK
|
||||
|
||||
* Log warning and adjust when BatchLogRecordProcessor, BatchSpanProcessor `maxExportBatchSize`
|
||||
exceeds `maxQueueSize`.
|
||||
([#7045](https://github.com/open-telemetry/opentelemetry-java/pull/7045),
|
||||
[#7148](https://github.com/open-telemetry/opentelemetry-java/pull/7148))
|
||||
* Fix bug causing `ThrottlingLogger` to log more than once per minute
|
||||
([#7156](https://github.com/open-telemetry/opentelemetry-java/pull/7156))
|
||||
|
||||
#### Metrics
|
||||
|
||||
* Remove obsolete `SdkMeterProviderUtil#setCardinalitylimit` API
|
||||
([#7169](https://github.com/open-telemetry/opentelemetry-java/pull/7169))
|
||||
|
||||
#### Traces
|
||||
|
||||
* Fix bug preventing accurate reporting of span event dropped attribute count
|
||||
([#7142](https://github.com/open-telemetry/opentelemetry-java/pull/7142))
|
||||
|
||||
#### Exporters
|
||||
|
||||
* OTLP: remove support for `otel.java.experimental.exporter.memory_mode`
|
||||
which was previously replaced by `otel.java.exporter.memory_mode`
|
||||
([#7127](https://github.com/open-telemetry/opentelemetry-java/pull/7127))
|
||||
* OTLP: Extract sender parameters to config carrier class
|
||||
(incubating API)
|
||||
([#7151](https://github.com/open-telemetry/opentelemetry-java/pull/7151))
|
||||
* OTLP: Add support for setting OTLP exporter service class loader
|
||||
([#7150](https://github.com/open-telemetry/opentelemetry-java/pull/7150))
|
||||
|
||||
### Tooling
|
||||
|
||||
* Update android animalsniffer min API version to 23
|
||||
([#7153](https://github.com/open-telemetry/opentelemetry-java/pull/7153))
|
||||
|
||||
## Version 1.47.0 (2025-02-07)
|
||||
|
||||
### API
|
||||
|
||||
#### Incubator
|
||||
|
@ -1736,7 +1970,7 @@ This release is a notable release for metrics:
|
|||
* Autoconfigure performs percent decoding on `otel.resource.attributes` values.
|
||||
[(#4653)](https://github.com/open-telemetry/opentelemetry-java/issues/4653)
|
||||
* Unify compression configuration for exporters including
|
||||
[(#4775)](https://github.com/open-telemetry/opentelemetry-java/issues/4775):
|
||||
[(#4775)](https://github.com/open-telemetry/opentelemetry-java/pull/4775):
|
||||
* Fix handling of `none` in OTLP exporters.
|
||||
* Add `JaegerGrpcSpanExporterBuilder#setCompression(String)`.
|
||||
* Add `ZipkinSpanExporterBuilder#setCompression(String)`.
|
||||
|
|
112
README.md
112
README.md
|
@ -1,7 +1,10 @@
|
|||
# OpenTelemetry Java
|
||||
[![Continuous Build][ci-image]][ci-url]
|
||||
[![Coverage Status][codecov-image]][codecov-url]
|
||||
|
||||
[![Maven Central][maven-image]][maven-url]
|
||||
[![Coverage Status][codecov-image]][codecov-url]
|
||||
[](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-java?ref=badge_shield&issueType=license)
|
||||
[](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-java?ref=badge_shield&issueType=security)
|
||||
[](https://scorecard.dev/viewer/?uri=github.com/open-telemetry/opentelemetry-java)
|
||||
[](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/io/opentelemetry/java/README.md)
|
||||
|
||||
`opentelemetry-java` is the home of the Java implementation of the OpenTelemetry API for recording
|
||||
|
@ -54,8 +57,8 @@ A bill of materials (or BOM) helps sync dependency versions of related artifacts
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|----------------------------------------------|----------------------------------------|---------------------------|-------------------------------------------------------------|---------|
|
||||
| [Bill of Materials (BOM)](./bom) | Bill of materials for stable artifacts | `opentelemetry-bom` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | N/A |
|
||||
| [Alpha Bill of Materials (BOM)](./bom-alpha) | Bill of materials for alpha artifacts | `opentelemetry-bom-alpha` | <!--VERSION_UNSTABLE-->1.46.0-alpha<!--/VERSION_UNSTABLE--> | N/A |
|
||||
| [Bill of Materials (BOM)](./bom) | Bill of materials for stable artifacts | `opentelemetry-bom` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | N/A |
|
||||
| [Alpha Bill of Materials (BOM)](./bom-alpha) | Bill of materials for alpha artifacts | `opentelemetry-bom-alpha` | <!--VERSION_UNSTABLE-->1.52.0-alpha<!--/VERSION_UNSTABLE--> | N/A |
|
||||
</details>
|
||||
|
||||
<details open>
|
||||
|
@ -65,9 +68,10 @@ The OpenTelemetry API for recording telemetry.
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|-----------------------------------|--------------------------------------------------------------------------------------|-------------------------------|-------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [API](./api/all) | OpenTelemetry API, including metrics, traces, baggage, context | `opentelemetry-api` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api) |
|
||||
| [API Incubator](./api/incubator) | API incubator, including pass through propagator, and extended tracer, and Event API | `opentelemetry-api-incubator` | <!--VERSION_UNSTABLE-->1.46.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api-incubator) |
|
||||
| [Context API](./context) | OpenTelemetry context API | `opentelemetry-context` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context) |
|
||||
| [API](./api/all) | OpenTelemetry API, including metrics, traces, baggage, context | `opentelemetry-api` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api) |
|
||||
| [API Incubator](./api/incubator) | API incubator, including pass through propagator, and extended tracer, and Event API | `opentelemetry-api-incubator` | <!--VERSION_UNSTABLE-->1.52.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api-incubator) |
|
||||
| [Context API](./context) | OpenTelemetry context API | `opentelemetry-context` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context) |
|
||||
| [Common](./common) | Common utility methods used across API components | `opentelemetry-common` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-common) |
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
@ -77,8 +81,8 @@ Extensions to the OpenTelemetry API.
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|---------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [Kotlin Extension](./extensions/kotlin) | Context extension for coroutines | `opentelemetry-extension-kotlin` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-extension-kotlin) |
|
||||
| [Trace Propagators Extension](./extensions/trace-propagators) | Trace propagators, including B3, Jaeger, OT Trace | `opentelemetry-extension-trace-propagators` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-extension-trace-propagators) |
|
||||
| [Kotlin Extension](./extensions/kotlin) | Context extension for coroutines | `opentelemetry-extension-kotlin` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-extension-kotlin) |
|
||||
| [Trace Propagators Extension](./extensions/trace-propagators) | Trace propagators, including B3, Jaeger, OT Trace | `opentelemetry-extension-trace-propagators` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-extension-trace-propagators) |
|
||||
</details>
|
||||
|
||||
<details open>
|
||||
|
@ -88,12 +92,12 @@ The OpenTelemetry SDK for managing telemetry producing by the API.
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|------------------------------|--------------------------------------------------------|-----------------------------|---------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [SDK](./sdk/all) | OpenTelemetry SDK, including metrics, traces, and logs | `opentelemetry-sdk` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk) |
|
||||
| [Metrics SDK](./sdk/metrics) | OpenTelemetry metrics SDK | `opentelemetry-sdk-metrics` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics) |
|
||||
| [Trace SDK](./sdk/trace) | OpenTelemetry trace SDK | `opentelemetry-sdk-trace` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace) |
|
||||
| [Log SDK](./sdk/logs) | OpenTelemetry log SDK | `opentelemetry-sdk-logs` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs) |
|
||||
| [SDK Common](./sdk/common) | Shared SDK components | `opentelemetry-sdk-common` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-common) |
|
||||
| [SDK Testing](./sdk/testing) | Components for testing OpenTelemetry instrumentation | `opentelemetry-sdk-testing` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-testing) |
|
||||
| [SDK](./sdk/all) | OpenTelemetry SDK, including metrics, traces, and logs | `opentelemetry-sdk` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk) |
|
||||
| [Metrics SDK](./sdk/metrics) | OpenTelemetry metrics SDK | `opentelemetry-sdk-metrics` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics) |
|
||||
| [Trace SDK](./sdk/trace) | OpenTelemetry trace SDK | `opentelemetry-sdk-trace` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace) |
|
||||
| [Log SDK](./sdk/logs) | OpenTelemetry log SDK | `opentelemetry-sdk-logs` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs) |
|
||||
| [SDK Common](./sdk/common) | Shared SDK components | `opentelemetry-sdk-common` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-common) |
|
||||
| [SDK Testing](./sdk/testing) | Components for testing OpenTelemetry instrumentation | `opentelemetry-sdk-testing` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-testing) |
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
@ -103,16 +107,16 @@ SDK exporters for shipping traces, metrics, and logs out of process.
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|-----------------------------------------------------------------------|------------------------------------------------------------------------------|------------------------------------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [OTLP Exporters](./exporters/otlp/all) | OTLP gRPC & HTTP exporters, including traces, metrics, and logs | `opentelemetry-exporter-otlp` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp) |
|
||||
| [OTLP Logging Exporters](./exporters/logging-otlp) | Logging exporters in OTLP JSON encoding, including traces, metrics, and logs | `opentelemetry-exporter-logging-otlp` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging-otlp) |
|
||||
| [OTLP Common](./exporters/otlp/common) | Shared OTLP components (internal) | `opentelemetry-exporter-otlp-common` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp-common) |
|
||||
| [Logging Exporter](./exporters/logging) | Logging exporters, including metrics, traces, and logs | `opentelemetry-exporter-logging` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging) |
|
||||
| [Zipkin Exporter](./exporters/zipkin) | Zipkin trace exporter | `opentelemetry-exporter-zipkin` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-zipkin) |
|
||||
| [Prometheus Exporter](./exporters/prometheus) | Prometheus metric exporter | `opentelemetry-exporter-prometheus` | <!--VERSION_UNSTABLE-->1.46.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-prometheus) |
|
||||
| [Exporter Common](./exporters/common) | Shared exporter components (internal) | `opentelemetry-exporter-common` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-common) |
|
||||
| [OkHttp Sender](./exporters/sender/okhttp) | OkHttp implementation of HttpSender (internal) | `opentelemetry-exporter-sender-okhttp` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-okhttp) |
|
||||
| [JDK Sender](./exporters/sender/jdk) | Java 11+ native HttpClient implementation of HttpSender (internal) | `opentelemetry-exporter-sender-jdk` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-jdk) | |
|
||||
| [gRPC ManagedChannel Sender](./exporters/sender/grpc-managed-channel) | gRPC ManagedChannel implementation of GrpcSender (internal) | `opentelemetry-exporter-sender-grpc-managed-channel` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-grpc-managed-channel) | |
|
||||
| [OTLP Exporters](./exporters/otlp/all) | OTLP gRPC & HTTP exporters, including traces, metrics, and logs | `opentelemetry-exporter-otlp` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp) |
|
||||
| [OTLP Logging Exporters](./exporters/logging-otlp) | Logging exporters in OTLP JSON encoding, including traces, metrics, and logs | `opentelemetry-exporter-logging-otlp` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging-otlp) |
|
||||
| [OTLP Common](./exporters/otlp/common) | Shared OTLP components (internal) | `opentelemetry-exporter-otlp-common` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp-common) |
|
||||
| [Logging Exporter](./exporters/logging) | Logging exporters, including metrics, traces, and logs | `opentelemetry-exporter-logging` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging) |
|
||||
| [Zipkin Exporter](./exporters/zipkin) | Zipkin trace exporter | `opentelemetry-exporter-zipkin` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-zipkin) |
|
||||
| [Prometheus Exporter](./exporters/prometheus) | Prometheus metric exporter | `opentelemetry-exporter-prometheus` | <!--VERSION_UNSTABLE-->1.52.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-prometheus) |
|
||||
| [Exporter Common](./exporters/common) | Shared exporter components (internal) | `opentelemetry-exporter-common` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-common) |
|
||||
| [OkHttp Sender](./exporters/sender/okhttp) | OkHttp implementation of HttpSender (internal) | `opentelemetry-exporter-sender-okhttp` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-okhttp) |
|
||||
| [JDK Sender](./exporters/sender/jdk) | Java 11+ native HttpClient implementation of HttpSender (internal) | `opentelemetry-exporter-sender-jdk` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-jdk) | |
|
||||
| [gRPC ManagedChannel Sender](./exporters/sender/grpc-managed-channel) | gRPC ManagedChannel implementation of GrpcSender (internal) | `opentelemetry-exporter-sender-grpc-managed-channel` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-grpc-managed-channel) | |
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
@ -122,10 +126,10 @@ Extensions to the OpenTelemetry SDK.
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|-------------------------------------------------------------------------------|------------------------------------------------------------------------------------|-----------------------------------------------------|-------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [SDK Autoconfigure](./sdk-extensions/autoconfigure) | Autoconfigure OpenTelemetry SDK from env vars, system properties, and SPI | `opentelemetry-sdk-extension-autoconfigure` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure) |
|
||||
| [SDK Autoconfigure SPI](./sdk-extensions/autoconfigure-spi) | Service Provider Interface (SPI) definitions for autoconfigure | `opentelemetry-sdk-extension-autoconfigure-spi` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi) |
|
||||
| [SDK Jaeger Remote Sampler Extension](./sdk-extensions/jaeger-remote-sampler) | Sampler which obtains sampling configuration from remote Jaeger server | `opentelemetry-sdk-extension-jaeger-remote-sampler` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-jaeger-remote-sampler) |
|
||||
| [SDK Incubator](./sdk-extensions/incubator) | SDK incubator, including YAML based view configuration, LeakDetectingSpanProcessor | `opentelemetry-sdk-extension-incubator` | <!--VERSION_UNSTABLE-->1.46.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-incubator) |
|
||||
| [SDK Autoconfigure](./sdk-extensions/autoconfigure) | Autoconfigure OpenTelemetry SDK from env vars, system properties, and SPI | `opentelemetry-sdk-extension-autoconfigure` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure) |
|
||||
| [SDK Autoconfigure SPI](./sdk-extensions/autoconfigure-spi) | Service Provider Interface (SPI) definitions for autoconfigure | `opentelemetry-sdk-extension-autoconfigure-spi` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi) |
|
||||
| [SDK Jaeger Remote Sampler Extension](./sdk-extensions/jaeger-remote-sampler) | Sampler which obtains sampling configuration from remote Jaeger server | `opentelemetry-sdk-extension-jaeger-remote-sampler` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-jaeger-remote-sampler) |
|
||||
| [SDK Incubator](./sdk-extensions/incubator) | SDK incubator, including YAML based view configuration, LeakDetectingSpanProcessor | `opentelemetry-sdk-extension-incubator` | <!--VERSION_UNSTABLE-->1.52.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-incubator) |
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
@ -135,8 +139,8 @@ Shims for bridging data from one observability library to another.
|
|||
|
||||
| Component | Description | Artifact ID | Version | Javadoc |
|
||||
|----------------------------------------|--------------------------------------------------------------|----------------------------------|-------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [OpenCensus Shim](./opencensus-shim) | Bridge opencensus metrics into the OpenTelemetry metrics SDK | `opentelemetry-opencensus-shim` | <!--VERSION_UNSTABLE-->1.46.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opencensus-shim) |
|
||||
| [OpenTracing Shim](./opentracing-shim) | Bridge opentracing spans into the OpenTelemetry trace API | `opentelemetry-opentracing-shim` | <!--VERSION_STABLE-->1.46.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opentracing-shim) |
|
||||
| [OpenCensus Shim](./opencensus-shim) | Bridge opencensus metrics into the OpenTelemetry metrics SDK | `opentelemetry-opencensus-shim` | <!--VERSION_UNSTABLE-->1.52.0-alpha<!--/VERSION_UNSTABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opencensus-shim) |
|
||||
| [OpenTracing Shim](./opentracing-shim) | Bridge opentracing spans into the OpenTelemetry trace API | `opentelemetry-opentracing-shim` | <!--VERSION_STABLE-->1.52.0<!--/VERSION_STABLE--> | [](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-opentracing-shim) |
|
||||
</details>
|
||||
|
||||
## Dependencies
|
||||
|
@ -173,11 +177,11 @@ Snapshots of the `main` branch are available as follows:
|
|||
|
||||
```groovy
|
||||
repositories {
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
|
||||
maven { url 'https://central.sonatype.com/repository/maven-snapshots/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation platform("io.opentelemetry:opentelemetry-bom:1.47.0-SNAPSHOT")
|
||||
implementation platform("io.opentelemetry:opentelemetry-bom:1.53.0-SNAPSHOT")
|
||||
implementation('io.opentelemetry:opentelemetry-api')
|
||||
}
|
||||
```
|
||||
|
@ -190,8 +194,8 @@ dependencies {
|
|||
<project>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>oss.sonatype.org-snapshot</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<id>sonatype-snapshot-repository</id>
|
||||
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencyManagement>
|
||||
|
@ -199,7 +203,7 @@ dependencies {
|
|||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-bom</artifactId>
|
||||
<version>1.47.0-SNAPSHOT</version>
|
||||
<version>1.53.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
@ -251,35 +255,35 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for:
|
|||
* Keys to successful PRs
|
||||
* Guide to using gradle composite builds
|
||||
|
||||
### Code owners
|
||||
### Maintainers
|
||||
|
||||
Triagers:
|
||||
- [Jack Berg](https://github.com/jack-berg), New Relic
|
||||
- [John Watson](https://github.com/jkwatson), Verta.ai
|
||||
|
||||
- [Gregor Zeitlinger](https://github.com/zeitlinger), Grafana Labs
|
||||
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
|
||||
|
||||
*Find more about the triager role in [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).*
|
||||
|
||||
Approvers ([@open-telemetry/java-approvers](https://github.com/orgs/open-telemetry/teams/java-approvers)):
|
||||
### Approvers
|
||||
|
||||
- [Jason Plumb](https://github.com/breedx-splk), Splunk
|
||||
- [Josh Suereth](https://github.com/jsuereth), Google
|
||||
- [Lauri Tulmin](https://github.com/laurit), Splunk
|
||||
- [Trask Stalnaker](https://github.com/trask), Microsoft
|
||||
|
||||
*Find more about the approver role in [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).*
|
||||
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
|
||||
|
||||
Maintainers ([@open-telemetry/java-maintainers](https://github.com/orgs/open-telemetry/teams/java-maintainers)):
|
||||
### Triagers
|
||||
|
||||
- [Jack Berg](https://github.com/jack-berg), New Relic
|
||||
- [John Watson](https://github.com/jkwatson), Verta.ai
|
||||
- [Gregor Zeitlinger](https://github.com/zeitlinger), Grafana Labs
|
||||
|
||||
Emeritus:
|
||||
For more information about the triager role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).
|
||||
|
||||
### Emeritus
|
||||
|
||||
- Maintainer [Bogdan Drutu](https://github.com/BogdanDrutu)
|
||||
- Maintainer [Carlos Alberto](https://github.com/carlosalberto)
|
||||
- Approver [Mateusz Rzeszutek](https://github.com/mateuszrzeszutek)
|
||||
|
||||
*Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).*
|
||||
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
|
||||
|
||||
### Help wanted
|
||||
|
||||
|
@ -290,18 +294,14 @@ We are currently resource constrained and are actively seeking new contributors
|
|||
- Issues labeled [help wanted](https://github.com/open-telemetry/opentelemetry-java/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) are project priorities. Code contributions (or pull request reviews when a PR is linked) for these issues are particularly important.
|
||||
- Triaging / responding to new issues and discussions is a great way to engage with the project.
|
||||
|
||||
### Thanks to all the people who have contributed
|
||||
### Thanks to all of our contributors!
|
||||
|
||||
<a href="https://github.com/open-telemetry/opentelemetry-java/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=open-telemetry/opentelemetry-java" />
|
||||
<img alt="Repo contributors" src="https://contrib.rocks/image?repo=open-telemetry/opentelemetry-java" />
|
||||
</a>
|
||||
|
||||
Made with [contrib.rocks](https://contrib.rocks).
|
||||
|
||||
[ci-image]: https://github.com/open-telemetry/opentelemetry-java/workflows/Build/badge.svg
|
||||
[ci-url]: https://github.com/open-telemetry/opentelemetry-java/actions?query=workflow%3ABuild+branch%3Amain
|
||||
[codecov-image]: https://codecov.io/gh/open-telemetry/opentelemetry-java/branch/main/graph/badge.svg
|
||||
[codecov-url]: https://app.codecov.io/gh/open-telemetry/opentelemetry-java/branch/main/
|
||||
[dependencies-and-boms]: https://opentelemetry.io/docs/languages/java/intro/#dependencies-and-boms
|
||||
[maven-image]: https://maven-badges.herokuapp.com/maven-central/io.opentelemetry/opentelemetry-api/badge.svg
|
||||
[maven-url]: https://maven-badges.herokuapp.com/maven-central/io.opentelemetry/opentelemetry-api
|
||||
[maven-image]: https://maven-badges.sml.io/maven-central/io.opentelemetry/opentelemetry-api/badge.svg
|
||||
[maven-url]: https://maven-badges.sml.io/maven-central/io.opentelemetry/opentelemetry-api
|
||||
|
|
20
RELEASING.md
20
RELEASING.md
|
@ -57,27 +57,17 @@ and deadlocks.
|
|||
* Review and merge the pull request that it creates for updating the change log in main
|
||||
(note that if this is not a patch release then the change log on main may already be up-to-date,
|
||||
in which case no pull request will be created).
|
||||
* Once the release artifacts become available on Maven Central, the system will automatically
|
||||
generate a new pull request titled `Update apidiff baseline and documentation versions to
|
||||
released version $VERSION`. This pull request will contain updates to both the API diff baseline
|
||||
and version references in the documentation files (README.md). Please review and merge this
|
||||
automated pull request.
|
||||
* The [website](https://github.com/open-telemetry/opentelemetry.io) contains automation to update
|
||||
to the newly released version. Review and approve the pull request when available.
|
||||
* The [website](https://opentelemetry.io/docs/languages/java/configuration/#zero-code-sdk-autoconfigure)
|
||||
contains documentation on autoconfiguration properties. If the release has updated or modified any
|
||||
properties, open and merge a pull request to update the documentation.
|
||||
|
||||
## Update release versions in documentations
|
||||
|
||||
After releasing is done, you need to first update the docs. This needs to happen after artifacts have propagated
|
||||
to Maven Central so should probably be done an hour or two after the release workflow finishes.
|
||||
|
||||
```
|
||||
./gradlew updateVersionInDocs -Prelease.version=x.y.z
|
||||
./gradlew japicmp -PapiBaseVersion=a.b.c -PapiNewVersion=x.y.z
|
||||
./gradlew --refresh-dependencies japicmp
|
||||
```
|
||||
|
||||
Where `x.y.z` is the version just released and `a.b.c` is the previous version.
|
||||
|
||||
Create a PR against the main branch with the changes.
|
||||
|
||||
## Credentials
|
||||
|
||||
The following credentials are required for building or publishing (and automatically set in Github Actions):
|
||||
|
|
|
@ -72,8 +72,8 @@ respect to semantic versioning.
|
|||
| Language | Minimum Version | Applicability | Semconv Notes |
|
||||
|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Java | 8+ | All artifacts, unless otherwise noted | Changing requires major version bump. |
|
||||
| Android | 21+ (NOTE: [desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring) is required. We stay up to date with the latest version of [desugar_jdk_libs](https://github.com/google/desugar_jdk_libs).) | Artifacts using `otel.animalsniffer-conventions` plugin | Kept in sync with minimum requirements for [Google Play services](https://developers.google.com/android/guides/setup). Subject to change in minor version. |
|
||||
| Kotlin | 1.6+ | Only applies to `opentelemetry-extension-kotlin` | Kept in sync with [minimum non-deprecated](https://kotlinlang.org/docs/gradle-compiler-options.html#attributes-common-to-jvm-and-js) version. Subject to change in minor versions. |
|
||||
| Android | 23+ (NOTE: [desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring) is required. We stay up to date with the latest version of [desugar_jdk_libs](https://github.com/google/desugar_jdk_libs).) | Artifacts using `otel.animalsniffer-conventions` plugin | Kept in sync with minimum requirements for [Google Play services](https://developers.google.com/android/guides/setup). Subject to change in minor version. |
|
||||
| Kotlin | 1.8+ | Only applies to `opentelemetry-extension-kotlin` | Kept in sync with [minimum non-deprecated](https://kotlinlang.org/docs/gradle-compiler-options.html#attributes-common-to-jvm-and-js) version. Subject to change in minor versions. |
|
||||
|
||||
## API vs SDK
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class SdkDesignTest {
|
|||
* Ensures that all SDK methods that: - are defined in classes that extend or implement API model
|
||||
* and are public (to exclude protected builders) - are public (avoids issues with protected
|
||||
* methods returning classes unavailable to test's CL) - override or implement parent method
|
||||
* return only API, Context or generic Java type.
|
||||
* return only API, Context, Common, or generic Java type.
|
||||
*/
|
||||
@Test
|
||||
void sdkImplementationOfApiClassesShouldReturnApiTypeOnly() {
|
||||
|
@ -45,7 +45,11 @@ class SdkDesignTest {
|
|||
.and(implementOrOverride())
|
||||
.should()
|
||||
.haveRawReturnType(
|
||||
inPackage("io.opentelemetry.api..", "io.opentelemetry.context..", "java.."))
|
||||
inPackage(
|
||||
"io.opentelemetry.api..",
|
||||
"io.opentelemetry.context..",
|
||||
"io.opentelemetry.common..",
|
||||
"java.."))
|
||||
.orShould()
|
||||
.haveRawReturnType("void");
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ configurations.add(signatureJarClasspath)
|
|||
configurations.add(generatedSignature)
|
||||
|
||||
dependencies {
|
||||
signature("com.toasttab.android:gummy-bears-api-21:0.10.0@signature")
|
||||
signature("com.toasttab.android:gummy-bears-api-23:0.12.0@signature")
|
||||
signatureJar("com.android.tools:desugar_jdk_libs")
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import io.opentelemetry.api.trace.TracerProvider;
|
|||
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -116,6 +117,21 @@ public final class GlobalOpenTelemetry {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OpenTelemetry} that should be the global instance.
|
||||
*
|
||||
* <p>This method calls the given {@code supplier} and calls {@link #set(OpenTelemetry)}, all
|
||||
* while holding the {@link GlobalOpenTelemetry} mutex.
|
||||
*
|
||||
* @since 1.52.0
|
||||
*/
|
||||
public static void set(Supplier<OpenTelemetry> supplier) {
|
||||
synchronized (mutex) {
|
||||
OpenTelemetry openTelemetry = supplier.get();
|
||||
set(openTelemetry);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the globally registered {@link TracerProvider}. */
|
||||
public static TracerProvider getTracerProvider() {
|
||||
return get().getTracerProvider();
|
||||
|
|
|
@ -16,7 +16,6 @@ import io.opentelemetry.context.Context;
|
|||
import io.opentelemetry.context.propagation.TextMapGetter;
|
||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||
import io.opentelemetry.context.propagation.TextMapSetter;
|
||||
import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -97,33 +96,11 @@ public final class W3CBaggagePropagator implements TextMapPropagator {
|
|||
return context;
|
||||
}
|
||||
|
||||
if (getter instanceof ExtendedTextMapGetter) {
|
||||
return extractMulti(context, carrier, (ExtendedTextMapGetter<C>) getter);
|
||||
}
|
||||
return extractSingle(context, carrier, getter);
|
||||
}
|
||||
|
||||
private static <C> Context extractSingle(
|
||||
Context context, @Nullable C carrier, TextMapGetter<C> getter) {
|
||||
String baggageHeader = getter.get(carrier, FIELD);
|
||||
if (baggageHeader == null) {
|
||||
return context;
|
||||
}
|
||||
if (baggageHeader.isEmpty()) {
|
||||
return context;
|
||||
}
|
||||
|
||||
BaggageBuilder baggageBuilder = Baggage.builder();
|
||||
try {
|
||||
extractEntries(baggageHeader, baggageBuilder);
|
||||
} catch (RuntimeException e) {
|
||||
return context;
|
||||
}
|
||||
return context.with(baggageBuilder.build());
|
||||
return extractMulti(context, carrier, getter);
|
||||
}
|
||||
|
||||
private static <C> Context extractMulti(
|
||||
Context context, @Nullable C carrier, ExtendedTextMapGetter<C> getter) {
|
||||
Context context, @Nullable C carrier, TextMapGetter<C> getter) {
|
||||
Iterator<String> baggageHeaders = getter.getAll(carrier, FIELD);
|
||||
if (baggageHeaders == null) {
|
||||
return context;
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class ArrayBackedAttributesBuilder implements AttributesBuilder {
|
||||
private final List<Object> data;
|
||||
|
@ -37,7 +38,7 @@ class ArrayBackedAttributesBuilder implements AttributesBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> AttributesBuilder put(AttributeKey<T> key, T value) {
|
||||
public <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value) {
|
||||
if (key == null || key.getKey().isEmpty() || value == null) {
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,11 @@ public interface AttributeKey<T> {
|
|||
/** Returns the type of attribute for this key. Useful for building switch statements. */
|
||||
AttributeType getType();
|
||||
|
||||
// TODO (jack-berg): uncomment when extended attributes are promoted from incubator to API
|
||||
// default ExtendedAttributeKey<T> asExtendedAttributeKey() {
|
||||
// return InternalAttributeKeyImpl.toExtendedAttributeKey(this);
|
||||
// }
|
||||
|
||||
/** Returns a new AttributeKey for String valued attributes. */
|
||||
static AttributeKey<String> stringKey(String key) {
|
||||
return InternalAttributeKeyImpl.create(key, AttributeType.STRING);
|
||||
|
|
|
@ -18,6 +18,7 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** A builder of {@link Attributes} supporting an arbitrary number of key-value pairs. */
|
||||
public interface AttributesBuilder {
|
||||
|
@ -35,18 +36,22 @@ public interface AttributesBuilder {
|
|||
// version.
|
||||
<T> AttributesBuilder put(AttributeKey<Long> key, int value);
|
||||
|
||||
/** Puts a {@link AttributeKey} with associated value into this. */
|
||||
<T> AttributesBuilder put(AttributeKey<T> key, T value);
|
||||
/**
|
||||
* Puts an {@link AttributeKey} with an associated value into this if the value is non-null.
|
||||
* Providing a null value does not remove or unset previously set values.
|
||||
*/
|
||||
<T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value);
|
||||
|
||||
/**
|
||||
* Puts a String attribute into this.
|
||||
* Puts a String attribute into this if the value is non-null. Providing a null value does not
|
||||
* remove or unset previously set values.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate
|
||||
* your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default AttributesBuilder put(String key, String value) {
|
||||
default AttributesBuilder put(String key, @Nullable String value) {
|
||||
return put(stringKey(key), value);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import io.opentelemetry.api.common.Value;
|
|||
import io.opentelemetry.context.Context;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class DefaultLogger implements Logger {
|
||||
|
||||
|
@ -77,7 +78,7 @@ class DefaultLogger implements Logger {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> LogRecordBuilder setAttribute(AttributeKey<T> key, T value) {
|
||||
public <T> LogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,18 @@
|
|||
|
||||
package io.opentelemetry.api.logs;
|
||||
|
||||
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
|
||||
import static io.opentelemetry.api.common.AttributeKey.doubleKey;
|
||||
import static io.opentelemetry.api.common.AttributeKey.longKey;
|
||||
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.Value;
|
||||
import io.opentelemetry.context.Context;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Used to construct and emit log records from a {@link Logger}.
|
||||
|
@ -98,8 +104,111 @@ public interface LogRecordBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Sets an attribute. */
|
||||
<T> LogRecordBuilder setAttribute(AttributeKey<T> key, T value);
|
||||
/**
|
||||
* Sets an attribute on the {@code LogRecord}. If the {@code LogRecord} previously contained a
|
||||
* mapping for the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: Providing a null value is a no-op and will not remove previously set values.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
*/
|
||||
<T> LogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value);
|
||||
|
||||
/**
|
||||
* Sets a String attribute on the {@code LogRecord}. If the {@code LogRecord} previously contained
|
||||
* a mapping for the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: Providing a null value is a no-op and will not remove previously set values.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
* @since 1.48.0
|
||||
*/
|
||||
default LogRecordBuilder setAttribute(String key, @Nullable String value) {
|
||||
return setAttribute(stringKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Long attribute on the {@code LogRecord}. If the {@code LogRecord} previously contained a
|
||||
* mapping for the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
* @since 1.48.0
|
||||
*/
|
||||
default LogRecordBuilder setAttribute(String key, long value) {
|
||||
return setAttribute(longKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Double attribute on the {@code LogRecord}. If the {@code LogRecord} previously contained
|
||||
* a mapping for the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
* @since 1.48.0
|
||||
*/
|
||||
default LogRecordBuilder setAttribute(String key, double value) {
|
||||
return setAttribute(doubleKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Boolean attribute on the {@code LogRecord}. If the {@code LogRecord} previously
|
||||
* contained a mapping for the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
* @since 1.48.0
|
||||
*/
|
||||
default LogRecordBuilder setAttribute(String key, boolean value) {
|
||||
return setAttribute(booleanKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an Integer attribute on the {@code LogRecord}. If the {@code LogRecord} previously
|
||||
* contained a mapping for the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
* @since 1.48.0
|
||||
*/
|
||||
default LogRecordBuilder setAttribute(String key, int value) {
|
||||
return setAttribute(key, (long) value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event name, which identifies the class / type of the Event.
|
||||
*
|
||||
* <p>This name should uniquely identify the event structure (both attributes and body). A log
|
||||
* record with a non-empty event name is an Event.
|
||||
*
|
||||
* @since 1.50.0
|
||||
*/
|
||||
default LogRecordBuilder setEventName(String eventName) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Emit the log record. */
|
||||
void emit();
|
||||
|
|
|
@ -8,6 +8,7 @@ package io.opentelemetry.api.trace;
|
|||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +43,7 @@ final class PropagatedSpan implements Span {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Span setAttribute(String key, String value) {
|
||||
public Span setAttribute(String key, @Nullable String value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ final class PropagatedSpan implements Span {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> Span setAttribute(AttributeKey<T> key, T value) {
|
||||
public <T> Span setAttribute(AttributeKey<T> key, @Nullable T value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,9 @@ public interface Span extends ImplicitContextKeyed {
|
|||
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
|
||||
* the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Empty String "" and null are valid attribute {@code value}, but not valid keys.
|
||||
* <p>Empty String "" and null are valid attribute {@code value}s, but not valid keys.
|
||||
*
|
||||
* <p>Note: Providing a null value is a no-op and will not remove previously set values.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
|
@ -97,7 +99,7 @@ public interface Span extends ImplicitContextKeyed {
|
|||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
*/
|
||||
default Span setAttribute(String key, String value) {
|
||||
default Span setAttribute(String key, @Nullable String value) {
|
||||
return setAttribute(AttributeKey.stringKey(key), value);
|
||||
}
|
||||
|
||||
|
@ -150,13 +152,13 @@ public interface Span extends ImplicitContextKeyed {
|
|||
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
|
||||
* the key, the old value is replaced by the specified value.
|
||||
*
|
||||
* <p>Note: the behavior of null values is undefined, and hence strongly discouraged.
|
||||
* <p>Note: Providing a null value is a no-op.
|
||||
*
|
||||
* @param key the key for this attribute.
|
||||
* @param value the value for this attribute.
|
||||
* @return this.
|
||||
*/
|
||||
<T> Span setAttribute(AttributeKey<T> key, T value);
|
||||
<T> Span setAttribute(AttributeKey<T> key, @Nullable T value);
|
||||
|
||||
/**
|
||||
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
|
||||
|
|
|
@ -14,7 +14,6 @@ import io.opentelemetry.api.baggage.Baggage;
|
|||
import io.opentelemetry.api.baggage.BaggageEntryMetadata;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.propagation.TextMapGetter;
|
||||
import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -40,8 +39,8 @@ class W3CBaggagePropagatorTest {
|
|||
}
|
||||
};
|
||||
|
||||
private static final ExtendedTextMapGetter<Map<String, List<String>>> multiGetter =
|
||||
new ExtendedTextMapGetter<Map<String, List<String>>>() {
|
||||
private static final TextMapGetter<Map<String, List<String>>> multiGetter =
|
||||
new TextMapGetter<Map<String, List<String>>>() {
|
||||
@Override
|
||||
public Iterable<String> keys(Map<String, List<String>> carrier) {
|
||||
return carrier.keySet();
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
|
|||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link Attributes}s. */
|
||||
|
@ -565,7 +566,7 @@ class AttributesTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> AttributesBuilder put(AttributeKey<T> key, T value) {
|
||||
public <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ Experimental APIs, including Event API, extended Log Bridge APIs, extended Metri
|
|||
Features:
|
||||
|
||||
* Check if logger is enabled before emitting logs to avoid unnecessary computation
|
||||
* Add extended attributes to log records to encode complex data structures
|
||||
|
||||
See [ExtendedLogsBridgeApiUsageTest](./src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java).
|
||||
|
||||
|
|
|
@ -12,8 +12,14 @@ otelJava.moduleName.set("io.opentelemetry.api.incubator")
|
|||
dependencies {
|
||||
api(project(":api:all"))
|
||||
|
||||
// Supports optional InstrumentationConfigUtil#convertToModel
|
||||
compileOnly("com.fasterxml.jackson.core:jackson-databind")
|
||||
|
||||
annotationProcessor("com.google.auto.value:auto-value")
|
||||
|
||||
// To use parsed config file as input for InstrumentationConfigUtilTest
|
||||
testImplementation(project(":sdk-extensions:incubator"))
|
||||
|
||||
testImplementation(project(":sdk:testing"))
|
||||
testImplementation(project(":api:testing-internal"))
|
||||
|
||||
|
@ -21,3 +27,16 @@ dependencies {
|
|||
|
||||
testImplementation("com.google.guava:guava")
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
register<JvmTestSuite>("testConvertToModel") {
|
||||
dependencies {
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind")
|
||||
implementation(project(":sdk-extensions:incubator"))
|
||||
implementation(project(":sdk-extensions:autoconfigure"))
|
||||
implementation("com.google.guava:guava")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.api.internal.ImmutableKeyValuePairs;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class ArrayBackedExtendedAttributes
|
||||
extends ImmutableKeyValuePairs<ExtendedAttributeKey<?>, Object> implements ExtendedAttributes {
|
||||
|
||||
// We only compare the key name, not type, when constructing, to allow deduping keys with the
|
||||
// same name but different type.
|
||||
private static final Comparator<ExtendedAttributeKey<?>> KEY_COMPARATOR_FOR_CONSTRUCTION =
|
||||
Comparator.comparing(ExtendedAttributeKey::getKey);
|
||||
|
||||
static final ExtendedAttributes EMPTY = ExtendedAttributes.builder().build();
|
||||
|
||||
@Nullable private Attributes attributes;
|
||||
|
||||
private ArrayBackedExtendedAttributes(
|
||||
Object[] data, Comparator<ExtendedAttributeKey<?>> keyComparator) {
|
||||
super(data, keyComparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only use this constructor if you can guarantee that the data has been de-duped, sorted by key
|
||||
* and contains no null values or null/empty keys.
|
||||
*
|
||||
* @param data the raw data
|
||||
*/
|
||||
ArrayBackedExtendedAttributes(Object[] data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedAttributesBuilder toBuilder() {
|
||||
return new ArrayBackedExtendedAttributesBuilder(new ArrayList<>(data()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T get(ExtendedAttributeKey<T> key) {
|
||||
return (T) super.get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Attributes asAttributes() {
|
||||
if (attributes == null) {
|
||||
AttributesBuilder builder = Attributes.builder();
|
||||
forEach(
|
||||
(extendedAttributeKey, value) -> {
|
||||
AttributeKey<Object> attributeKey =
|
||||
(AttributeKey<Object>) extendedAttributeKey.asAttributeKey();
|
||||
if (attributeKey != null) {
|
||||
builder.put(attributeKey, value);
|
||||
}
|
||||
});
|
||||
attributes = builder.build();
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
static ExtendedAttributes sortAndFilterToAttributes(Object... data) {
|
||||
// null out any empty keys or keys with null values
|
||||
// so they will then be removed by the sortAndFilter method.
|
||||
for (int i = 0; i < data.length; i += 2) {
|
||||
ExtendedAttributeKey<?> key = (ExtendedAttributeKey<?>) data[i];
|
||||
if (key != null && key.getKey().isEmpty()) {
|
||||
data[i] = null;
|
||||
}
|
||||
}
|
||||
return new ArrayBackedExtendedAttributes(data, KEY_COMPARATOR_FOR_CONSTRUCTION);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
class ArrayBackedExtendedAttributesBuilder implements ExtendedAttributesBuilder {
|
||||
private final List<Object> data;
|
||||
|
||||
ArrayBackedExtendedAttributesBuilder() {
|
||||
data = new ArrayList<>();
|
||||
}
|
||||
|
||||
ArrayBackedExtendedAttributesBuilder(List<Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedAttributes build() {
|
||||
// If only one key-value pair AND the entry hasn't been set to null (by #remove(AttributeKey<T>)
|
||||
// or #removeIf(Predicate<AttributeKey<?>>)), then we can bypass sorting and filtering
|
||||
if (data.size() == 2 && data.get(0) != null) {
|
||||
return new ArrayBackedExtendedAttributes(data.toArray());
|
||||
}
|
||||
return ArrayBackedExtendedAttributes.sortAndFilterToAttributes(data.toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ExtendedAttributesBuilder put(ExtendedAttributeKey<T> key, T value) {
|
||||
if (key == null || key.getKey().isEmpty() || value == null) {
|
||||
return this;
|
||||
}
|
||||
data.add(key);
|
||||
data.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedAttributesBuilder removeIf(Predicate<ExtendedAttributeKey<?>> predicate) {
|
||||
if (predicate == null) {
|
||||
return this;
|
||||
}
|
||||
for (int i = 0; i < data.size() - 1; i += 2) {
|
||||
Object entry = data.get(i);
|
||||
if (entry instanceof ExtendedAttributeKey
|
||||
&& predicate.test((ExtendedAttributeKey<?>) entry)) {
|
||||
// null items are filtered out in ArrayBackedAttributes
|
||||
data.set(i, null);
|
||||
data.set(i + 1, null);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static List<Double> toList(double... values) {
|
||||
Double[] boxed = new Double[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
boxed[i] = values[i];
|
||||
}
|
||||
return Arrays.asList(boxed);
|
||||
}
|
||||
|
||||
static List<Long> toList(long... values) {
|
||||
Long[] boxed = new Long[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
boxed[i] = values[i];
|
||||
}
|
||||
return Arrays.asList(boxed);
|
||||
}
|
||||
|
||||
static List<Boolean> toList(boolean... values) {
|
||||
Boolean[] boxed = new Boolean[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
boxed[i] = values[i];
|
||||
}
|
||||
return Arrays.asList(boxed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.incubator.internal.InternalExtendedAttributeKeyImpl;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* This interface provides a handle for setting the values of {@link ExtendedAttributes}. The type
|
||||
* of value that can be set with an implementation of this key is denoted by the type parameter.
|
||||
*
|
||||
* <p>Implementations MUST be immutable, as these are used as the keys to Maps.
|
||||
*
|
||||
* <p>The allowed {@link #getType()}s is a superset of those allowed in {@link AttributeKey}.
|
||||
*
|
||||
* <p>Convenience methods are provided for translating to / from {@link AttributeKey}:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #asAttributeKey()} converts from {@link ExtendedAttributeKey} to {@link
|
||||
* AttributeKey}
|
||||
* <li>{@link #fromAttributeKey(AttributeKey)} converts from {@link AttributeKey} to {@link
|
||||
* ExtendedAttributeKey}
|
||||
* </ul>
|
||||
*
|
||||
* @param <T> The type of value that can be set with the key.
|
||||
*/
|
||||
@Immutable
|
||||
public interface ExtendedAttributeKey<T> {
|
||||
/** Returns the underlying String representation of the key. */
|
||||
String getKey();
|
||||
|
||||
/** Returns the type of attribute for this key. Useful for building switch statements. */
|
||||
ExtendedAttributeType getType();
|
||||
|
||||
/**
|
||||
* Return the equivalent {@link AttributeKey}, or {@code null} if the {@link #getType()} has no
|
||||
* equivalent {@link io.opentelemetry.api.common.AttributeType}.
|
||||
*/
|
||||
@Nullable
|
||||
default AttributeKey<T> asAttributeKey() {
|
||||
return InternalExtendedAttributeKeyImpl.toAttributeKey(this);
|
||||
}
|
||||
|
||||
/** Return an ExtendedAttributeKey equivalent to the {@code attributeKey}. */
|
||||
// TODO (jack-berg): remove once AttributeKey.asExtendedAttributeKey is available
|
||||
static <T> ExtendedAttributeKey<T> fromAttributeKey(AttributeKey<T> attributeKey) {
|
||||
return InternalExtendedAttributeKeyImpl.toExtendedAttributeKey(attributeKey);
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for String valued attributes. */
|
||||
static ExtendedAttributeKey<String> stringKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.stringKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for Boolean valued attributes. */
|
||||
static ExtendedAttributeKey<Boolean> booleanKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.booleanKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for Long valued attributes. */
|
||||
static ExtendedAttributeKey<Long> longKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.longKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for Double valued attributes. */
|
||||
static ExtendedAttributeKey<Double> doubleKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.doubleKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for List<String> valued attributes. */
|
||||
static ExtendedAttributeKey<List<String>> stringArrayKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.stringArrayKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for List<Boolean> valued attributes. */
|
||||
static ExtendedAttributeKey<List<Boolean>> booleanArrayKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.booleanArrayKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for List<Long> valued attributes. */
|
||||
static ExtendedAttributeKey<List<Long>> longArrayKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.longArrayKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for List<Double> valued attributes. */
|
||||
static ExtendedAttributeKey<List<Double>> doubleArrayKey(String key) {
|
||||
return fromAttributeKey(AttributeKey.doubleArrayKey(key));
|
||||
}
|
||||
|
||||
/** Returns a new ExtendedAttributeKey for Map valued attributes. */
|
||||
static ExtendedAttributeKey<ExtendedAttributes> extendedAttributesKey(String key) {
|
||||
return InternalExtendedAttributeKeyImpl.create(key, ExtendedAttributeType.EXTENDED_ATTRIBUTES);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
/**
|
||||
* An enum that represents all the possible value types for an {@link ExtendedAttributeKey} and
|
||||
* hence the types of values that are allowed for {@link ExtendedAttributes}.
|
||||
*
|
||||
* <p>This is a superset of {@link io.opentelemetry.api.common.AttributeType},
|
||||
*/
|
||||
public enum ExtendedAttributeType {
|
||||
// Types copied AttributeType
|
||||
STRING,
|
||||
BOOLEAN,
|
||||
LONG,
|
||||
DOUBLE,
|
||||
STRING_ARRAY,
|
||||
BOOLEAN_ARRAY,
|
||||
LONG_ARRAY,
|
||||
DOUBLE_ARRAY,
|
||||
// Extended types unique to ExtendedAttributes
|
||||
EXTENDED_ATTRIBUTES;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* An immutable container for extended attributes.
|
||||
*
|
||||
* <p>"extended" refers an extended set of allowed value types compared to standard {@link
|
||||
* Attributes}. Notably, {@link ExtendedAttributes} values can be of type {@link
|
||||
* ExtendedAttributeType#EXTENDED_ATTRIBUTES}, allowing nested {@link ExtendedAttributes} of
|
||||
* arbitrary depth.
|
||||
*
|
||||
* <p>Where standard {@link Attributes} are accepted everyone that OpenTelemetry represents key /
|
||||
* value pairs, {@link ExtendedAttributes} are only accepted in select places, such as log records
|
||||
* (e.g. {@link ExtendedLogRecordBuilder#setAttribute(ExtendedAttributeKey, Object)}).
|
||||
*
|
||||
* <p>The keys are {@link ExtendedAttributeKey}s and the values are Object instances that match the
|
||||
* type of the provided key.
|
||||
*
|
||||
* <p>Null keys will be silently dropped.
|
||||
*
|
||||
* <p>Note: The behavior of null-valued attributes is undefined, and hence strongly discouraged.
|
||||
*
|
||||
* <p>Implementations of this interface *must* be immutable and have well-defined value-based
|
||||
* equals/hashCode implementations. If an implementation does not strictly conform to these
|
||||
* requirements, behavior of the OpenTelemetry APIs and default SDK cannot be guaranteed.
|
||||
*
|
||||
* <p>For this reason, it is strongly suggested that you use the implementation that is provided
|
||||
* here via the factory methods and the {@link ExtendedAttributesBuilder}.
|
||||
*
|
||||
* <p>Convenience methods are provided for translating to / from {@link Attributes}:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #asAttributes()} converts from {@link ExtendedAttributes} to {@link Attributes}
|
||||
* <li>{@link ExtendedAttributesBuilder#putAll(Attributes)} converts from {@link Attributes} to
|
||||
* {@link ExtendedAttributes}
|
||||
* <li>{@link #get(AttributeKey)} supports reading values using standard {@link AttributeKey}
|
||||
* </ul>
|
||||
*/
|
||||
@Immutable
|
||||
public interface ExtendedAttributes {
|
||||
|
||||
/** Returns the value for the given {@link AttributeKey}, or {@code null} if not found. */
|
||||
@Nullable
|
||||
default <T> T get(AttributeKey<T> key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
return get(ExtendedAttributeKey.fromAttributeKey(key));
|
||||
}
|
||||
|
||||
/** Returns the value for the given {@link ExtendedAttributeKey}, or {@code null} if not found. */
|
||||
@Nullable
|
||||
<T> T get(ExtendedAttributeKey<T> key);
|
||||
|
||||
/** Iterates over all the key-value pairs of attributes contained by this instance. */
|
||||
void forEach(BiConsumer<? super ExtendedAttributeKey<?>, ? super Object> consumer);
|
||||
|
||||
/** The number of attributes contained in this. */
|
||||
int size();
|
||||
|
||||
/** Whether there are any attributes contained in this. */
|
||||
boolean isEmpty();
|
||||
|
||||
/** Returns a read-only view of this {@link ExtendedAttributes} as a {@link Map}. */
|
||||
Map<ExtendedAttributeKey<?>, Object> asMap();
|
||||
|
||||
/**
|
||||
* Return a view of this extended attributes with entries limited to those representable as
|
||||
* standard attributes.
|
||||
*/
|
||||
Attributes asAttributes();
|
||||
|
||||
/** Returns a {@link ExtendedAttributes} instance with no attributes. */
|
||||
static ExtendedAttributes empty() {
|
||||
return ArrayBackedExtendedAttributes.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link ExtendedAttributesBuilder} instance for creating arbitrary {@link
|
||||
* ExtendedAttributes}.
|
||||
*/
|
||||
static ExtendedAttributesBuilder builder() {
|
||||
return new ArrayBackedExtendedAttributesBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link ExtendedAttributesBuilder} instance populated with the data of this {@link
|
||||
* ExtendedAttributes}.
|
||||
*/
|
||||
ExtendedAttributesBuilder toBuilder();
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import static io.opentelemetry.api.incubator.common.ArrayBackedExtendedAttributesBuilder.toList;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.booleanArrayKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.booleanKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.doubleArrayKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.doubleKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.longArrayKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.longKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.stringArrayKey;
|
||||
import static io.opentelemetry.api.incubator.common.ExtendedAttributeKey.stringKey;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/** A builder of {@link ExtendedAttributes} supporting an arbitrary number of key-value pairs. */
|
||||
public interface ExtendedAttributesBuilder {
|
||||
/** Create the {@link ExtendedAttributes} from this. */
|
||||
ExtendedAttributes build();
|
||||
|
||||
/** Puts a {@link AttributeKey} with associated value into this. */
|
||||
default <T> ExtendedAttributesBuilder put(AttributeKey<T> key, T value) {
|
||||
if (key == null || key.getKey().isEmpty() || value == null) {
|
||||
return this;
|
||||
}
|
||||
return put(ExtendedAttributeKey.fromAttributeKey(key), value);
|
||||
}
|
||||
|
||||
/** Puts a {@link ExtendedAttributeKey} with associated value into this. */
|
||||
<T> ExtendedAttributesBuilder put(ExtendedAttributeKey<T> key, T value);
|
||||
|
||||
/**
|
||||
* Puts a String attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, String value) {
|
||||
return put(stringKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a long attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, long value) {
|
||||
return put(longKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a double attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, double value) {
|
||||
return put(doubleKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a boolean attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, boolean value) {
|
||||
return put(booleanKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a {@link ExtendedAttributes} attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default <T> ExtendedAttributesBuilder put(String key, ExtendedAttributes value) {
|
||||
return put(ExtendedAttributeKey.extendedAttributesKey(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a String array attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, String... value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
return put(stringArrayKey(key), Arrays.asList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a List attribute into this.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> ExtendedAttributesBuilder put(AttributeKey<List<T>> key, T... value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
return put(key, Arrays.asList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a Long array attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, long... value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
return put(longArrayKey(key), toList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a Double array attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, double... value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
return put(doubleArrayKey(key), toList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a Boolean array attribute into this.
|
||||
*
|
||||
* <p>Note: It is strongly recommended to use {@link #put(ExtendedAttributeKey, Object)}, and
|
||||
* pre-allocate your keys, if possible.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default ExtendedAttributesBuilder put(String key, boolean... value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
return put(booleanArrayKey(key), toList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all the provided attributes into this Builder.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
default ExtendedAttributesBuilder putAll(Attributes attributes) {
|
||||
if (attributes == null) {
|
||||
return this;
|
||||
}
|
||||
attributes.forEach((key, value) -> put((AttributeKey<Object>) key, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all the provided attributes into this Builder.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
default ExtendedAttributesBuilder putAll(ExtendedAttributes attributes) {
|
||||
if (attributes == null) {
|
||||
return this;
|
||||
}
|
||||
attributes.forEach((key, value) -> put((ExtendedAttributeKey<Object>) key, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all attributes where {@link AttributeKey#getKey()} and {@link AttributeKey#getType()}
|
||||
* match the {@code key}.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default <T> ExtendedAttributesBuilder remove(AttributeKey<T> key) {
|
||||
return remove(ExtendedAttributeKey.fromAttributeKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all attributes where {@link ExtendedAttributeKey#getKey()} and {@link
|
||||
* ExtendedAttributeKey#getType()} match the {@code key}.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
default <T> ExtendedAttributesBuilder remove(ExtendedAttributeKey<T> key) {
|
||||
if (key == null || key.getKey().isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
return removeIf(
|
||||
entryKey ->
|
||||
key.getKey().equals(entryKey.getKey()) && key.getType().equals(entryKey.getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all attributes that satisfy the given predicate. Errors or runtime exceptions thrown by
|
||||
* the predicate are relayed to the caller.
|
||||
*
|
||||
* @return this Builder
|
||||
*/
|
||||
ExtendedAttributesBuilder removeIf(Predicate<ExtendedAttributeKey<?>> filter);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* A registry for accessing declarative configuration.
|
||||
*
|
||||
* <p>The name <i>Provider</i> is for consistency with other languages and it is <b>NOT</b> loaded
|
||||
* using reflection.
|
||||
*
|
||||
* <p>See {@link InstrumentationConfigUtil} for convenience methods for extracting config from
|
||||
* {@link ConfigProvider}.
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface ConfigProvider {
|
||||
|
||||
/**
|
||||
* Returns the {@link DeclarativeConfigProperties} corresponding to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-configuration/blob/main/schema/instrumentation.json">instrumentation
|
||||
* config</a>, or {@code null} if unavailable.
|
||||
*
|
||||
* @return the instrumentation {@link DeclarativeConfigProperties}
|
||||
*/
|
||||
@Nullable
|
||||
DeclarativeConfigProperties getInstrumentationConfig();
|
||||
|
||||
/** Returns a no-op {@link ConfigProvider}. */
|
||||
static ConfigProvider noop() {
|
||||
return () -> null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
/** An exception that is thrown when errors occur with declarative configuration. */
|
||||
public final class DeclarativeConfigException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 3036584181551130522L;
|
||||
|
||||
/** Create a new configuration exception with specified {@code message} and without a cause. */
|
||||
public DeclarativeConfigException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/** Create a new configuration exception with specified {@code message} and {@code cause}. */
|
||||
public DeclarativeConfigException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -3,20 +3,20 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.autoconfigure.spi.internal;
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import static io.opentelemetry.api.internal.ConfigUtil.defaultIfNull;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.common.ComponentLoader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An interface for accessing structured configuration data.
|
||||
* An interface for accessing declarative configuration data.
|
||||
*
|
||||
* <p>An instance of {@link StructuredConfigProperties} is equivalent to a <a
|
||||
* <p>An instance of {@link DeclarativeConfigProperties} is equivalent to a <a
|
||||
* href="https://yaml.org/spec/1.2.2/#3211-nodes">YAML mapping node</a>. It has accessors for
|
||||
* reading scalar properties, {@link #getStructured(String)} for reading children which are
|
||||
* themselves mappings, and {@link #getStructuredList(String)} for reading children which are
|
||||
|
@ -25,24 +25,29 @@ import javax.annotation.Nullable;
|
|||
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
|
||||
* at any time.
|
||||
*/
|
||||
public interface StructuredConfigProperties {
|
||||
public interface DeclarativeConfigProperties {
|
||||
|
||||
/**
|
||||
* Return an empty {@link StructuredConfigProperties} instance.
|
||||
* Return an empty {@link DeclarativeConfigProperties} instance.
|
||||
*
|
||||
* <p>Useful for walking the tree without checking for null. For example, to access a string key
|
||||
* nested at .foo.bar.baz, call: {@code config.getStructured("foo", empty()).getStructured("bar",
|
||||
* empty()).getString("baz")}.
|
||||
*/
|
||||
static StructuredConfigProperties empty() {
|
||||
return EmptyStructuredConfigProperties.getInstance();
|
||||
static DeclarativeConfigProperties empty() {
|
||||
return EmptyDeclarativeConfigProperties.getInstance();
|
||||
}
|
||||
|
||||
/** Return a map representation of the {@code declarativeConfigProperties}. */
|
||||
static Map<String, Object> toMap(DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return DeclarativeConfigPropertyUtil.toMap(declarativeConfigProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link String} configuration property.
|
||||
*
|
||||
* @return null if the property has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar string
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar string
|
||||
*/
|
||||
@Nullable
|
||||
String getString(String name);
|
||||
|
@ -52,7 +57,7 @@ public interface StructuredConfigProperties {
|
|||
*
|
||||
* @return a {@link String} configuration property or {@code defaultValue} if a property with
|
||||
* {@code name} has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar string
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar string
|
||||
*/
|
||||
default String getString(String name, String defaultValue) {
|
||||
return defaultIfNull(getString(name), defaultValue);
|
||||
|
@ -63,7 +68,7 @@ public interface StructuredConfigProperties {
|
|||
* {@link Boolean#parseBoolean(String)} for handling the values.
|
||||
*
|
||||
* @return null if the property has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar boolean
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar boolean
|
||||
*/
|
||||
@Nullable
|
||||
Boolean getBoolean(String name);
|
||||
|
@ -73,7 +78,7 @@ public interface StructuredConfigProperties {
|
|||
*
|
||||
* @return a {@link Boolean} configuration property or {@code defaultValue} if a property with
|
||||
* {@code name} has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar boolean
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar boolean
|
||||
*/
|
||||
default boolean getBoolean(String name, boolean defaultValue) {
|
||||
return defaultIfNull(getBoolean(name), defaultValue);
|
||||
|
@ -86,7 +91,7 @@ public interface StructuredConfigProperties {
|
|||
* {@link Long#intValue()} which may result in loss of precision.
|
||||
*
|
||||
* @return null if the property has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar integer
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar integer
|
||||
*/
|
||||
@Nullable
|
||||
Integer getInt(String name);
|
||||
|
@ -99,7 +104,7 @@ public interface StructuredConfigProperties {
|
|||
*
|
||||
* @return a {@link Integer} configuration property or {@code defaultValue} if a property with
|
||||
* {@code name} has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar integer
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar integer
|
||||
*/
|
||||
default int getInt(String name, int defaultValue) {
|
||||
return defaultIfNull(getInt(name), defaultValue);
|
||||
|
@ -109,7 +114,7 @@ public interface StructuredConfigProperties {
|
|||
* Returns a {@link Long} configuration property.
|
||||
*
|
||||
* @return null if the property has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar long
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar long
|
||||
*/
|
||||
@Nullable
|
||||
Long getLong(String name);
|
||||
|
@ -119,7 +124,7 @@ public interface StructuredConfigProperties {
|
|||
*
|
||||
* @return a {@link Long} configuration property or {@code defaultValue} if a property with {@code
|
||||
* name} has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar long
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar long
|
||||
*/
|
||||
default long getLong(String name, long defaultValue) {
|
||||
return defaultIfNull(getLong(name), defaultValue);
|
||||
|
@ -129,7 +134,7 @@ public interface StructuredConfigProperties {
|
|||
* Returns a {@link Double} configuration property.
|
||||
*
|
||||
* @return null if the property has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar double
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar double
|
||||
*/
|
||||
@Nullable
|
||||
Double getDouble(String name);
|
||||
|
@ -139,7 +144,7 @@ public interface StructuredConfigProperties {
|
|||
*
|
||||
* @return a {@link Double} configuration property or {@code defaultValue} if a property with
|
||||
* {@code name} has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid scalar double
|
||||
* @throws DeclarativeConfigException if the property is not a valid scalar double
|
||||
*/
|
||||
default double getDouble(String name, double defaultValue) {
|
||||
return defaultIfNull(getDouble(name), defaultValue);
|
||||
|
@ -153,8 +158,8 @@ public interface StructuredConfigProperties {
|
|||
* @param scalarType the scalar type, one of {@link String}, {@link Boolean}, {@link Long} or
|
||||
* {@link Double}
|
||||
* @return a {@link List} configuration property, or null if the property has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid sequence of scalars, or if {@code
|
||||
* scalarType} is not supported
|
||||
* @throws DeclarativeConfigException if the property is not a valid sequence of scalars, or if
|
||||
* {@code scalarType} is not supported
|
||||
*/
|
||||
@Nullable
|
||||
<T> List<T> getScalarList(String name, Class<T> scalarType);
|
||||
|
@ -163,56 +168,58 @@ public interface StructuredConfigProperties {
|
|||
* Returns a {@link List} configuration property. Entries which are not strings are converted to
|
||||
* their string representation.
|
||||
*
|
||||
* @see ConfigProperties#getList(String name)
|
||||
* @param name the property name
|
||||
* @param scalarType the scalar type, one of {@link String}, {@link Boolean}, {@link Long} or
|
||||
* {@link Double}
|
||||
* @return a {@link List} configuration property or {@code defaultValue} if a property with {@code
|
||||
* name} has not been configured
|
||||
* @throws ConfigurationException if the property is not a valid sequence of scalars
|
||||
* @throws DeclarativeConfigException if the property is not a valid sequence of scalars
|
||||
*/
|
||||
default <T> List<T> getScalarList(String name, Class<T> scalarType, List<T> defaultValue) {
|
||||
return defaultIfNull(getScalarList(name, scalarType), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link StructuredConfigProperties} configuration property.
|
||||
* Returns a {@link DeclarativeConfigProperties} configuration property.
|
||||
*
|
||||
* @return a map-valued configuration property, or {@code null} if {@code name} has not been
|
||||
* configured
|
||||
* @throws ConfigurationException if the property is not a mapping
|
||||
* @throws DeclarativeConfigException if the property is not a mapping
|
||||
*/
|
||||
@Nullable
|
||||
StructuredConfigProperties getStructured(String name);
|
||||
DeclarativeConfigProperties getStructured(String name);
|
||||
|
||||
/**
|
||||
* Returns a {@link StructuredConfigProperties} configuration property.
|
||||
* Returns a list of {@link DeclarativeConfigProperties} configuration property.
|
||||
*
|
||||
* @return a map-valued configuration property, or {@code defaultValue} if {@code name} has not
|
||||
* been configured
|
||||
* @throws ConfigurationException if the property is not a mapping
|
||||
* @throws DeclarativeConfigException if the property is not a mapping
|
||||
*/
|
||||
default StructuredConfigProperties getStructured(
|
||||
String name, StructuredConfigProperties defaultValue) {
|
||||
default DeclarativeConfigProperties getStructured(
|
||||
String name, DeclarativeConfigProperties defaultValue) {
|
||||
return defaultIfNull(getStructured(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of {@link StructuredConfigProperties} configuration property.
|
||||
* Returns a list of {@link DeclarativeConfigProperties} configuration property.
|
||||
*
|
||||
* @return a list of map-valued configuration property, or {@code null} if {@code name} has not
|
||||
* been configured
|
||||
* @throws ConfigurationException if the property is not a sequence of mappings
|
||||
* @throws DeclarativeConfigException if the property is not a sequence of mappings
|
||||
*/
|
||||
@Nullable
|
||||
List<StructuredConfigProperties> getStructuredList(String name);
|
||||
List<DeclarativeConfigProperties> getStructuredList(String name);
|
||||
|
||||
/**
|
||||
* Returns a list of {@link StructuredConfigProperties} configuration property.
|
||||
* Returns a list of {@link DeclarativeConfigProperties} configuration property.
|
||||
*
|
||||
* @return a list of map-valued configuration property, or {@code defaultValue} if {@code name}
|
||||
* has not been configured
|
||||
* @throws ConfigurationException if the property is not a sequence of mappings
|
||||
* @throws DeclarativeConfigException if the property is not a sequence of mappings
|
||||
*/
|
||||
default List<StructuredConfigProperties> getStructuredList(
|
||||
String name, List<StructuredConfigProperties> defaultValue) {
|
||||
default List<DeclarativeConfigProperties> getStructuredList(
|
||||
String name, List<DeclarativeConfigProperties> defaultValue) {
|
||||
return defaultIfNull(getStructuredList(name), defaultValue);
|
||||
}
|
||||
|
||||
|
@ -222,4 +229,7 @@ public interface StructuredConfigProperties {
|
|||
* @return the configuration property keys
|
||||
*/
|
||||
Set<String> getPropertyKeys();
|
||||
|
||||
/** Return a {@link ComponentLoader} that should be used to load SPIs. */
|
||||
ComponentLoader getComponentLoader();
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class DeclarativeConfigPropertyUtil {
|
||||
|
||||
private DeclarativeConfigPropertyUtil() {}
|
||||
|
||||
private static final List<BiFunction<String, DeclarativeConfigProperties, Object>>
|
||||
valueResolvers =
|
||||
Arrays.asList(
|
||||
DeclarativeConfigPropertyUtil::getString,
|
||||
DeclarativeConfigPropertyUtil::getBoolean,
|
||||
DeclarativeConfigPropertyUtil::getLong,
|
||||
DeclarativeConfigPropertyUtil::getDouble,
|
||||
DeclarativeConfigPropertyUtil::getStringList,
|
||||
DeclarativeConfigPropertyUtil::getBooleanList,
|
||||
DeclarativeConfigPropertyUtil::getLongList,
|
||||
DeclarativeConfigPropertyUtil::getDoubleList,
|
||||
DeclarativeConfigPropertyUtil::getStringList,
|
||||
DeclarativeConfigPropertyUtil::getStructuredList,
|
||||
DeclarativeConfigPropertyUtil::getStructured);
|
||||
|
||||
static Map<String, Object> toMap(DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
Set<String> propertyKeys = declarativeConfigProperties.getPropertyKeys();
|
||||
Map<String, Object> result = new HashMap<>(propertyKeys.size());
|
||||
for (String key : declarativeConfigProperties.getPropertyKeys()) {
|
||||
result.put(key, resolveValue(key, declarativeConfigProperties));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object resolveValue(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
for (int i = 0; i < valueResolvers.size(); i++) {
|
||||
try {
|
||||
Object value = valueResolvers.get(i).apply(key, declarativeConfigProperties);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
} catch (DeclarativeConfigException e) {
|
||||
// Ignore and continue
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getString(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getString(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getBoolean(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getBoolean(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getLong(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getLong(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getDouble(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getDouble(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getStringList(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getScalarList(key, String.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getBooleanList(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getScalarList(key, Boolean.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getLongList(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getScalarList(key, Long.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getDoubleList(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return declarativeConfigProperties.getScalarList(key, Double.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getStructuredList(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return Optional.ofNullable(declarativeConfigProperties.getStructuredList(key))
|
||||
.map(list -> list.stream().map(DeclarativeConfigPropertyUtil::toMap).collect(toList()))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getStructured(
|
||||
String key, DeclarativeConfigProperties declarativeConfigProperties) {
|
||||
return Optional.ofNullable(declarativeConfigProperties.getStructured(key))
|
||||
.map(DeclarativeConfigPropertyUtil::toMap)
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
|
@ -3,22 +3,25 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.autoconfigure.spi.internal;
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import io.opentelemetry.common.ComponentLoader;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Empty instance of {@link StructuredConfigProperties}. */
|
||||
final class EmptyStructuredConfigProperties implements StructuredConfigProperties {
|
||||
/** Empty instance of {@link DeclarativeConfigProperties}. */
|
||||
final class EmptyDeclarativeConfigProperties implements DeclarativeConfigProperties {
|
||||
|
||||
private static final EmptyStructuredConfigProperties INSTANCE =
|
||||
new EmptyStructuredConfigProperties();
|
||||
private static final EmptyDeclarativeConfigProperties INSTANCE =
|
||||
new EmptyDeclarativeConfigProperties();
|
||||
private static final ComponentLoader COMPONENT_LOADER =
|
||||
ComponentLoader.forClassLoader(EmptyDeclarativeConfigProperties.class.getClassLoader());
|
||||
|
||||
private EmptyStructuredConfigProperties() {}
|
||||
private EmptyDeclarativeConfigProperties() {}
|
||||
|
||||
static EmptyStructuredConfigProperties getInstance() {
|
||||
static EmptyDeclarativeConfigProperties getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -60,13 +63,13 @@ final class EmptyStructuredConfigProperties implements StructuredConfigPropertie
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public StructuredConfigProperties getStructured(String name) {
|
||||
public DeclarativeConfigProperties getStructured(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<StructuredConfigProperties> getStructuredList(String name) {
|
||||
public List<DeclarativeConfigProperties> getStructuredList(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -74,4 +77,9 @@ final class EmptyStructuredConfigProperties implements StructuredConfigPropertie
|
|||
public Set<String> getPropertyKeys() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentLoader getComponentLoader() {
|
||||
return COMPONENT_LOADER;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class provides a temporary global accessor for {@link ConfigProvider} until the
|
||||
* instrumentation config API is marked stable. It will eventually be merged into {@link
|
||||
* GlobalOpenTelemetry}.
|
||||
*/
|
||||
// We intentionally assign to be used for error reporting.
|
||||
@SuppressWarnings("StaticAssignmentOfThrowable")
|
||||
public final class GlobalConfigProvider {
|
||||
|
||||
private static final AtomicReference<ConfigProvider> instance =
|
||||
new AtomicReference<>(ConfigProvider.noop());
|
||||
|
||||
@SuppressWarnings("NonFinalStaticField")
|
||||
@Nullable
|
||||
private static volatile Throwable setInstanceCaller;
|
||||
|
||||
private GlobalConfigProvider() {}
|
||||
|
||||
/** Returns the globally registered {@link ConfigProvider}. */
|
||||
// instance cannot be set to null
|
||||
@SuppressWarnings("NullAway")
|
||||
public static ConfigProvider get() {
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the global {@link ConfigProvider}. Future calls to {@link #get()} will return the provided
|
||||
* {@link ConfigProvider} instance. This should be called once as early as possible in your
|
||||
* application initialization logic.
|
||||
*
|
||||
* @throws IllegalStateException when called more than once
|
||||
*/
|
||||
public static void set(ConfigProvider configProvider) {
|
||||
boolean changed = instance.compareAndSet(ConfigProvider.noop(), configProvider);
|
||||
if (!changed && (configProvider != ConfigProvider.noop())) {
|
||||
throw new IllegalStateException(
|
||||
"GlobalConfigProvider.set has already been called. GlobalConfigProvider.set "
|
||||
+ "must be called only once before any calls to GlobalConfigProvider.get. "
|
||||
+ "Previous invocation set to cause of this exception.",
|
||||
setInstanceCaller);
|
||||
}
|
||||
setInstanceCaller = new Throwable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets the global {@link ConfigProvider}. This is only meant to be used from tests which need
|
||||
* to reconfigure {@link ConfigProvider}.
|
||||
*/
|
||||
public static void resetForTest() {
|
||||
instance.set(ConfigProvider.noop());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A collection of convenience methods to extract instrumentation config from {@link
|
||||
* ConfigProvider#getInstrumentationConfig()}.
|
||||
*/
|
||||
public class InstrumentationConfigUtil {
|
||||
|
||||
/**
|
||||
* Return a map representation of the peer service map entries in {@code
|
||||
* .instrumentation.general.peer.service_mapping}, or null if none is configured.
|
||||
*
|
||||
* @throws DeclarativeConfigException if an unexpected type is encountered accessing the property
|
||||
*/
|
||||
@Nullable
|
||||
public static Map<String, String> peerServiceMapping(ConfigProvider configProvider) {
|
||||
List<DeclarativeConfigProperties> serviceMappingList =
|
||||
getOrNull(
|
||||
configProvider,
|
||||
config -> config.getStructuredList("service_mapping"),
|
||||
"general",
|
||||
"peer");
|
||||
if (serviceMappingList == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, String> serviceMapping = new LinkedHashMap<>();
|
||||
serviceMappingList.forEach(
|
||||
entry -> {
|
||||
String peer = entry.getString("peer");
|
||||
String service = entry.getString("service");
|
||||
if (peer != null && service != null) {
|
||||
serviceMapping.put(peer, service);
|
||||
}
|
||||
});
|
||||
return serviceMapping.isEmpty() ? null : serviceMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code .instrumentation.general.http.client.request_captured_headers}, or null if none
|
||||
* is configured.
|
||||
*
|
||||
* @throws DeclarativeConfigException if an unexpected type is encountered accessing the property
|
||||
*/
|
||||
@Nullable
|
||||
public static List<String> httpClientRequestCapturedHeaders(ConfigProvider configProvider) {
|
||||
return getOrNull(
|
||||
configProvider,
|
||||
config -> config.getScalarList("request_captured_headers", String.class),
|
||||
"general",
|
||||
"http",
|
||||
"client");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code .instrumentation.general.http.client.response_captured_headers}, or null if none
|
||||
* is configured.
|
||||
*
|
||||
* @throws DeclarativeConfigException if an unexpected type is encountered accessing the property
|
||||
*/
|
||||
@Nullable
|
||||
public static List<String> httpClientResponseCapturedHeaders(ConfigProvider configProvider) {
|
||||
return getOrNull(
|
||||
configProvider,
|
||||
config -> config.getScalarList("response_captured_headers", String.class),
|
||||
"general",
|
||||
"http",
|
||||
"client");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code .instrumentation.general.http.server.request_captured_headers}, or null if none
|
||||
* is configured.
|
||||
*
|
||||
* @throws DeclarativeConfigException if an unexpected type is encountered accessing the property
|
||||
*/
|
||||
@Nullable
|
||||
public static List<String> httpServerRequestCapturedHeaders(ConfigProvider configProvider) {
|
||||
return getOrNull(
|
||||
configProvider,
|
||||
config -> config.getScalarList("request_captured_headers", String.class),
|
||||
"general",
|
||||
"http",
|
||||
"server");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code .instrumentation.general.http.server.response_captured_headers}, or null if none
|
||||
* is configured.
|
||||
*
|
||||
* @throws DeclarativeConfigException if an unexpected type is encountered accessing the property
|
||||
*/
|
||||
@Nullable
|
||||
public static List<String> httpServerResponseCapturedHeaders(ConfigProvider configProvider) {
|
||||
return getOrNull(
|
||||
configProvider,
|
||||
config -> config.getScalarList("response_captured_headers", String.class),
|
||||
"general",
|
||||
"http",
|
||||
"server");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code .instrumentation.java.<instrumentationName>}, or null if none is configured.
|
||||
*
|
||||
* @throws DeclarativeConfigException if an unexpected type is encountered accessing the property
|
||||
*/
|
||||
@Nullable
|
||||
public static DeclarativeConfigProperties javaInstrumentationConfig(
|
||||
ConfigProvider configProvider, String instrumentationName) {
|
||||
return getOrNull(configProvider, config -> config.getStructured(instrumentationName), "java");
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk down the {@code segments} of {@link ConfigProvider#getInstrumentationConfig()} and call
|
||||
* {@code accessor} on the terminal node. Returns null if {@link
|
||||
* ConfigProvider#getInstrumentationConfig()} is null, or if null is encountered walking the
|
||||
* {@code segments}, or if {@code accessor} returns null.
|
||||
*
|
||||
* <p>See other methods in {@link InstrumentationConfigUtil} for usage examples.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T getOrNull(
|
||||
ConfigProvider configProvider,
|
||||
Function<DeclarativeConfigProperties, T> accessor,
|
||||
String... segments) {
|
||||
DeclarativeConfigProperties config = configProvider.getInstrumentationConfig();
|
||||
if (config == null) {
|
||||
return null;
|
||||
}
|
||||
for (String segment : segments) {
|
||||
config = config.getStructured(segment);
|
||||
if (config == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return accessor.apply(config);
|
||||
}
|
||||
|
||||
private InstrumentationConfigUtil() {}
|
||||
|
||||
/**
|
||||
* Return {@code .instrumentation.java.<instrumentationName>}, after converting it to the {@code
|
||||
* modelType} using the {@code objectMapper}. If no configuration exists for the {@code
|
||||
* instrumentationName}, returns {@code null}.
|
||||
*
|
||||
* <p>This method is a convenience method for a common instrumentation library workflow:
|
||||
*
|
||||
* <ul>
|
||||
* <li>During initialization, an instrumentation library is given an {@link ConfigProvider} and
|
||||
* must initialize according to the relevant config
|
||||
* <li>It checks if the user has provided configuration for it, and if so...
|
||||
* <li>It converts the configuration to an in-memory model representing all of its relevant
|
||||
* properties
|
||||
* <li>It initializes using the strongly typed in-memory model
|
||||
* </ul>
|
||||
*
|
||||
* <p>Conversion is done using {@link ObjectMapper#convertValue(Object, Class)} from {@code
|
||||
* com.fasterxml.jackson.databind}, and assumes the {@code modelType} is a POJO written /
|
||||
* annotated to support jackson databinding.
|
||||
*
|
||||
* <p>NOTE: callers MUST add their own dependency on {@code
|
||||
* com.fasterxml.jackson.core:jackson-databind}. This module's dependency is {@code compileOnly}
|
||||
* since jackson is a large dependency that many users will not require. It's very possible to
|
||||
* convert between {@link DeclarativeConfigProperties} (or a map representation from {@link
|
||||
* DeclarativeConfigProperties#toMap(DeclarativeConfigProperties)}) and a target model type
|
||||
* without jackson. This method is provided as an optional convenience method.
|
||||
*
|
||||
* @throws IllegalArgumentException if conversion fails. See {@link
|
||||
* ObjectMapper#convertValue(Object, Class)} for details.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T getInstrumentationConfigModel(
|
||||
ConfigProvider configProvider,
|
||||
String instrumentationName,
|
||||
ObjectMapper objectMapper,
|
||||
Class<T> modelType) {
|
||||
DeclarativeConfigProperties properties =
|
||||
javaInstrumentationConfig(configProvider, instrumentationName);
|
||||
if (properties == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> configPropertiesMap = DeclarativeConfigProperties.toMap(properties);
|
||||
return objectMapper.convertValue(configPropertiesMap, modelType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.internal;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.AttributeType;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributeKey;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributeType;
|
||||
import io.opentelemetry.api.internal.InternalAttributeKeyImpl;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public final class InternalExtendedAttributeKeyImpl<T> implements ExtendedAttributeKey<T> {
|
||||
|
||||
private final ExtendedAttributeType type;
|
||||
private final String key;
|
||||
private final int hashCode;
|
||||
|
||||
@Nullable private byte[] keyUtf8;
|
||||
@Nullable private AttributeKey<T> attributeKey;
|
||||
|
||||
private InternalExtendedAttributeKeyImpl(ExtendedAttributeType type, String key) {
|
||||
if (type == null) {
|
||||
throw new NullPointerException("Null type");
|
||||
}
|
||||
this.type = type;
|
||||
if (key == null) {
|
||||
throw new NullPointerException("Null key");
|
||||
}
|
||||
this.key = key;
|
||||
this.hashCode = buildHashCode(type, key);
|
||||
}
|
||||
|
||||
public static <T> ExtendedAttributeKey<T> create(
|
||||
@Nullable String key, ExtendedAttributeType type) {
|
||||
return new InternalExtendedAttributeKeyImpl<>(type, key != null ? key : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedAttributeType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AttributeKey<T> asAttributeKey() {
|
||||
if (attributeKey == null) {
|
||||
attributeKey = toAttributeKey(this);
|
||||
}
|
||||
return attributeKey;
|
||||
}
|
||||
|
||||
/** Returns the key, encoded as UTF-8 bytes. */
|
||||
public byte[] getKeyUtf8() {
|
||||
byte[] keyUtf8 = this.keyUtf8;
|
||||
if (keyUtf8 == null) {
|
||||
keyUtf8 = key.getBytes(StandardCharsets.UTF_8);
|
||||
this.keyUtf8 = keyUtf8;
|
||||
}
|
||||
return keyUtf8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof InternalExtendedAttributeKeyImpl) {
|
||||
InternalExtendedAttributeKeyImpl<?> that = (InternalExtendedAttributeKeyImpl<?>) o;
|
||||
return this.type.equals(that.getType()) && this.key.equals(that.getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return key;
|
||||
}
|
||||
|
||||
// this method exists to make EqualsVerifier happy
|
||||
@SuppressWarnings("unused")
|
||||
private int buildHashCode() {
|
||||
return buildHashCode(type, key);
|
||||
}
|
||||
|
||||
private static int buildHashCode(ExtendedAttributeType type, String key) {
|
||||
int result = 1;
|
||||
result *= 1000003;
|
||||
result ^= type.hashCode();
|
||||
result *= 1000003;
|
||||
result ^= key.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the equivalent {@link AttributeKey} for the {@link ExtendedAttributeKey}, or {@code
|
||||
* null} if the {@link #getType()} has no equivalent {@link
|
||||
* io.opentelemetry.api.common.AttributeType}.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> AttributeKey<T> toAttributeKey(ExtendedAttributeKey<T> extendedAttributeKey) {
|
||||
switch (extendedAttributeKey.getType()) {
|
||||
case STRING:
|
||||
return InternalAttributeKeyImpl.create(extendedAttributeKey.getKey(), AttributeType.STRING);
|
||||
case BOOLEAN:
|
||||
return InternalAttributeKeyImpl.create(
|
||||
extendedAttributeKey.getKey(), AttributeType.BOOLEAN);
|
||||
case LONG:
|
||||
return InternalAttributeKeyImpl.create(extendedAttributeKey.getKey(), AttributeType.LONG);
|
||||
case DOUBLE:
|
||||
return InternalAttributeKeyImpl.create(extendedAttributeKey.getKey(), AttributeType.DOUBLE);
|
||||
case STRING_ARRAY:
|
||||
return InternalAttributeKeyImpl.create(
|
||||
extendedAttributeKey.getKey(), AttributeType.STRING_ARRAY);
|
||||
case BOOLEAN_ARRAY:
|
||||
return InternalAttributeKeyImpl.create(
|
||||
extendedAttributeKey.getKey(), AttributeType.BOOLEAN_ARRAY);
|
||||
case LONG_ARRAY:
|
||||
return InternalAttributeKeyImpl.create(
|
||||
extendedAttributeKey.getKey(), AttributeType.LONG_ARRAY);
|
||||
case DOUBLE_ARRAY:
|
||||
return InternalAttributeKeyImpl.create(
|
||||
extendedAttributeKey.getKey(), AttributeType.DOUBLE_ARRAY);
|
||||
case EXTENDED_ATTRIBUTES:
|
||||
return null;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"Unrecognized extendedAttributeKey type: " + extendedAttributeKey.getType());
|
||||
}
|
||||
|
||||
/** Return the equivalent {@link ExtendedAttributeKey} for the {@link AttributeKey}. */
|
||||
public static <T> ExtendedAttributeKey<T> toExtendedAttributeKey(AttributeKey<T> attributeKey) {
|
||||
switch (attributeKey.getType()) {
|
||||
case STRING:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.STRING);
|
||||
case BOOLEAN:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.BOOLEAN);
|
||||
case LONG:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.LONG);
|
||||
case DOUBLE:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.DOUBLE);
|
||||
case STRING_ARRAY:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.STRING_ARRAY);
|
||||
case BOOLEAN_ARRAY:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.BOOLEAN_ARRAY);
|
||||
case LONG_ARRAY:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.LONG_ARRAY);
|
||||
case DOUBLE_ARRAY:
|
||||
return InternalExtendedAttributeKeyImpl.create(
|
||||
attributeKey.getKey(), ExtendedAttributeType.DOUBLE_ARRAY);
|
||||
}
|
||||
throw new IllegalArgumentException("Unrecognized attributeKey type: " + attributeKey.getType());
|
||||
}
|
||||
}
|
|
@ -7,12 +7,13 @@ package io.opentelemetry.api.incubator.logs;
|
|||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Value;
|
||||
import io.opentelemetry.api.logs.LogRecordBuilder;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributeKey;
|
||||
import io.opentelemetry.api.logs.Logger;
|
||||
import io.opentelemetry.api.logs.Severity;
|
||||
import io.opentelemetry.context.Context;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class ExtendedDefaultLogger implements ExtendedLogger {
|
||||
|
||||
|
@ -26,6 +27,11 @@ class ExtendedDefaultLogger implements ExtendedLogger {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(Severity severity, Context context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedLogRecordBuilder logRecordBuilder() {
|
||||
return NOOP_LOG_RECORD_BUILDER;
|
||||
|
@ -41,52 +47,62 @@ class ExtendedDefaultLogger implements ExtendedLogger {
|
|||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setTimestamp(long timestamp, TimeUnit unit) {
|
||||
public ExtendedLogRecordBuilder setException(Throwable throwable) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setTimestamp(Instant instant) {
|
||||
public <T> ExtendedLogRecordBuilder setAttribute(ExtendedAttributeKey<T> key, T value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setObservedTimestamp(long timestamp, TimeUnit unit) {
|
||||
public <T> ExtendedLogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setObservedTimestamp(Instant instant) {
|
||||
public ExtendedLogRecordBuilder setTimestamp(long timestamp, TimeUnit unit) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setContext(Context context) {
|
||||
public ExtendedLogRecordBuilder setTimestamp(Instant instant) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setSeverity(Severity severity) {
|
||||
public ExtendedLogRecordBuilder setObservedTimestamp(long timestamp, TimeUnit unit) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setSeverityText(String severityText) {
|
||||
public ExtendedLogRecordBuilder setObservedTimestamp(Instant instant) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setBody(String body) {
|
||||
public ExtendedLogRecordBuilder setContext(Context context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogRecordBuilder setBody(Value<?> body) {
|
||||
public ExtendedLogRecordBuilder setSeverity(Severity severity) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LogRecordBuilder setAttribute(AttributeKey<T> key, T value) {
|
||||
public ExtendedLogRecordBuilder setSeverityText(String severityText) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedLogRecordBuilder setBody(String body) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedLogRecordBuilder setBody(Value<?> body) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,18 +5,134 @@
|
|||
|
||||
package io.opentelemetry.api.incubator.logs;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.Value;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributeKey;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributes;
|
||||
import io.opentelemetry.api.logs.LogRecordBuilder;
|
||||
import io.opentelemetry.api.logs.Severity;
|
||||
import io.opentelemetry.context.Context;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Extended {@link LogRecordBuilder} with experimental APIs. */
|
||||
public interface ExtendedLogRecordBuilder extends LogRecordBuilder {
|
||||
|
||||
// keep this class even if it is empty, since experimental methods may be added in the future.
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setTimestamp(long timestamp, TimeUnit unit);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setTimestamp(Instant instant);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setObservedTimestamp(long timestamp, TimeUnit unit);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setObservedTimestamp(Instant instant);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setContext(Context context);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setSeverity(Severity severity);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setSeverityText(String severityText);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setBody(String body);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
default ExtendedLogRecordBuilder setBody(Value<?> body) {
|
||||
setBody(body.asString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event name, which identifies the class / type of the Event.
|
||||
*
|
||||
* <p>This name should uniquely identify the event structure (both attributes and body). A log
|
||||
* record with a non-empty event name is an Event.
|
||||
*/
|
||||
@Override
|
||||
ExtendedLogRecordBuilder setEventName(String eventName);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>NOTE: all standard {@link AttributeKey}-value pairs can also be represented as {@link
|
||||
* ExtendedAttributeKey}-value pairs, but not all {@link ExtendedAttributeKey}-value pairs can be
|
||||
* represented as standard {@link AttributeKey}-value pairs. From the standpoint of the emitted
|
||||
* log record, there is no difference between adding attributes using the standard or extended
|
||||
* attribute APIs.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
default ExtendedLogRecordBuilder setAllAttributes(Attributes attributes) {
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
attributes.forEach(
|
||||
(attributeKey, value) -> setAttribute((AttributeKey<Object>) attributeKey, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets attributes. If the {@link LogRecordBuilder} previously contained a mapping for any of the
|
||||
* keys, the old values are replaced by the specified values.
|
||||
*
|
||||
* <p>NOTE: all standard {@link AttributeKey}-value pairs can also be represented as {@link
|
||||
* ExtendedAttributeKey}-value pairs, but not all {@link ExtendedAttributeKey}-value pairs can be
|
||||
* represented as standard {@link AttributeKey}-value pairs. From the standpoint of the emitted
|
||||
* log record, there is no difference between adding attributes using the standard or extended
|
||||
* attribute APIs.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default ExtendedLogRecordBuilder setAllAttributes(ExtendedAttributes attributes) {
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
attributes.forEach(
|
||||
(attributeKey, value) -> setAttribute((ExtendedAttributeKey<Object>) attributeKey, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>NOTE: all standard {@link AttributeKey}-value pairs can also be represented as {@link
|
||||
* ExtendedAttributeKey}-value pairs, but not all {@link ExtendedAttributeKey}-value pairs can be
|
||||
* represented as standard {@link AttributeKey}-value pairs. From the standpoint of the emitted
|
||||
* log record, there is no difference between adding attributes using the standard or extended
|
||||
* attribute APIs.
|
||||
*/
|
||||
@Override
|
||||
<T> ExtendedLogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value);
|
||||
|
||||
/**
|
||||
* Set an attribute.
|
||||
*
|
||||
* <p>NOTE: all standard {@link AttributeKey}-value pairs can also be represented as {@link
|
||||
* ExtendedAttributeKey}-value pairs, but not all {@link ExtendedAttributeKey}-value pairs can be
|
||||
* represented as standard {@link AttributeKey}-value pairs. From the standpoint of the emitted
|
||||
* log record, there is no difference between adding attributes using the standard or extended
|
||||
* attribute APIs.
|
||||
*/
|
||||
<T> ExtendedLogRecordBuilder setAttribute(ExtendedAttributeKey<T> key, T value);
|
||||
|
||||
/** Set standard {@code exception.*} attributes based on the {@code throwable}. */
|
||||
ExtendedLogRecordBuilder setException(Throwable throwable);
|
||||
}
|
||||
|
|
|
@ -6,21 +6,41 @@
|
|||
package io.opentelemetry.api.incubator.logs;
|
||||
|
||||
import io.opentelemetry.api.logs.Logger;
|
||||
import io.opentelemetry.api.logs.Severity;
|
||||
import io.opentelemetry.context.Context;
|
||||
|
||||
/** Extended {@link Logger} with experimental APIs. */
|
||||
public interface ExtendedLogger extends Logger {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the logger is enabled.
|
||||
* Returns {@code true} if the logger is enabled for the given {@code context} and {@code
|
||||
* severity}.
|
||||
*
|
||||
* <p>This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
|
||||
* the response is subject to change over the application, callers should call this before each
|
||||
* call to {@link #logRecordBuilder()}.
|
||||
*/
|
||||
default boolean isEnabled() {
|
||||
default boolean isEnabled(Severity severity, Context context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Overload of {@link #isEnabled(Severity, Context)} assuming {@link Context#current()}. */
|
||||
default boolean isEnabled(Severity severity) {
|
||||
return isEnabled(severity, Context.current());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of {@link #isEnabled(Severity, Context)} assuming {@link
|
||||
* Severity#UNDEFINED_SEVERITY_NUMBER} and {@link Context#current()}.
|
||||
*
|
||||
* @deprecated for removal after 1.55.0. Use {@link #isEnabled(Severity, Context)} or {@link
|
||||
* #isEnabled(Severity)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean isEnabled() {
|
||||
return isEnabled(Severity.UNDEFINED_SEVERITY_NUMBER);
|
||||
}
|
||||
|
||||
@Override
|
||||
ExtendedLogRecordBuilder logRecordBuilder();
|
||||
}
|
||||
|
|
|
@ -94,6 +94,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
private ExtendedDefaultMeter() {}
|
||||
|
||||
private static class NoopLongCounter implements ExtendedLongCounter {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(long value, Attributes attributes, Context context) {}
|
||||
|
||||
|
@ -105,6 +110,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopDoubleCounter implements ExtendedDoubleCounter {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(double value, Attributes attributes, Context context) {}
|
||||
|
||||
|
@ -186,6 +196,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopLongUpDownCounter implements ExtendedLongUpDownCounter {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(long value, Attributes attributes, Context context) {}
|
||||
|
||||
|
@ -197,6 +212,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopDoubleUpDownCounter implements ExtendedDoubleUpDownCounter {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(double value, Attributes attributes, Context context) {}
|
||||
|
||||
|
@ -281,6 +301,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopDoubleHistogram implements ExtendedDoubleHistogram {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void record(double value, Attributes attributes, Context context) {}
|
||||
|
||||
|
@ -292,6 +317,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopLongHistogram implements ExtendedLongHistogram {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void record(long value, Attributes attributes, Context context) {}
|
||||
|
||||
|
@ -385,6 +415,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopDoubleGauge implements ExtendedDoubleGauge {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(double value) {}
|
||||
|
||||
|
@ -426,6 +461,11 @@ class ExtendedDefaultMeter implements Meter {
|
|||
}
|
||||
|
||||
private static class NoopLongGauge implements ExtendedLongGauge {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(long value) {}
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@ final class ExtendedDefaultTracer implements ExtendedTracer {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedSpanBuilder spanBuilder(String spanName) {
|
||||
return NoopSpanBuilder.create();
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.incubator.config.ConfigProvider;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ConfigProviderTest {
|
||||
|
||||
@Test
|
||||
void noopEquality() {
|
||||
ConfigProvider noop = ConfigProvider.noop();
|
||||
assertThat(ConfigProvider.noop()).isSameAs(noop);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class ExtendedAttributeKeyTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributeKeyArgs")
|
||||
void test(
|
||||
ExtendedAttributeKey<?> key,
|
||||
String expectedKey,
|
||||
ExtendedAttributeType expectedType,
|
||||
@Nullable AttributeKey<?> expectedAttributeKey) {
|
||||
assertThat(key.getKey()).isEqualTo(expectedKey);
|
||||
assertThat(key.getType()).isEqualTo(expectedType);
|
||||
assertThat(key.asAttributeKey()).isEqualTo(expectedAttributeKey);
|
||||
|
||||
if (expectedAttributeKey != null) {
|
||||
ExtendedAttributeKey<?> extendedAttributeKey =
|
||||
ExtendedAttributeKey.fromAttributeKey(expectedAttributeKey);
|
||||
assertThat(extendedAttributeKey).isEqualTo(key);
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream<Arguments> attributeKeyArgs() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.stringKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.STRING,
|
||||
AttributeKey.stringKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.booleanKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.BOOLEAN,
|
||||
AttributeKey.booleanKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.longKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.LONG,
|
||||
AttributeKey.longKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.doubleKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.DOUBLE,
|
||||
AttributeKey.doubleKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.stringArrayKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.STRING_ARRAY,
|
||||
AttributeKey.stringArrayKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.booleanArrayKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.BOOLEAN_ARRAY,
|
||||
AttributeKey.booleanArrayKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.longArrayKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.LONG_ARRAY,
|
||||
AttributeKey.longArrayKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.doubleArrayKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.DOUBLE_ARRAY,
|
||||
AttributeKey.doubleArrayKey("key")),
|
||||
Arguments.of(
|
||||
ExtendedAttributeKey.extendedAttributesKey("key"),
|
||||
"key",
|
||||
ExtendedAttributeType.EXTENDED_ATTRIBUTES,
|
||||
null));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.common;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class ExtendedAttributesTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void get_ExtendedAttributeKey(
|
||||
ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
expectedMap.forEach(
|
||||
(key, value) -> {
|
||||
ExtendedAttributeKey<?> extendedAttributeKey = getKey(key, value);
|
||||
Object actualValue = extendedAttributes.get(extendedAttributeKey);
|
||||
if (actualValue instanceof ExtendedAttributes) {
|
||||
Map<String, Object> mapValue = toMap((ExtendedAttributes) actualValue);
|
||||
actualValue = mapValue;
|
||||
}
|
||||
|
||||
assertThat(actualValue)
|
||||
.describedAs(key + "(" + extendedAttributeKey.getType() + ")")
|
||||
.isEqualTo(value);
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void get_AttributeKey(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
expectedMap.forEach(
|
||||
(key, value) -> {
|
||||
ExtendedAttributeKey<?> extendedAttributeKey = getKey(key, value);
|
||||
AttributeKey<?> attributeKey = extendedAttributeKey.asAttributeKey();
|
||||
|
||||
// Skip attribute keys which cannot be represented as AttributeKey
|
||||
if (attributeKey == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object actualValue = extendedAttributes.get(attributeKey);
|
||||
|
||||
assertThat(actualValue)
|
||||
.describedAs(key + "(" + attributeKey.getType() + ")")
|
||||
.isEqualTo(value);
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void forEach(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
// toMap uses .forEach to convert
|
||||
Map<String, Object> seenEntries = toMap(extendedAttributes);
|
||||
|
||||
assertThat(seenEntries).isEqualTo(expectedMap);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void size(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
assertThat(extendedAttributes.size()).isEqualTo(expectedMap.size());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void isEmpty(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
assertThat(extendedAttributes.isEmpty()).isEqualTo(expectedMap.isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void asMap(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
assertEquals(extendedAttributes.asMap(), expectedMap);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void assertEquals(
|
||||
Map<ExtendedAttributeKey<?>, Object> actual, Map<String, Object> expected) {
|
||||
assertThat(actual.size()).isEqualTo(expected.size());
|
||||
actual.forEach(
|
||||
(key, value) -> {
|
||||
if (key.getType() == ExtendedAttributeType.EXTENDED_ATTRIBUTES) {
|
||||
assertEquals(
|
||||
((ExtendedAttributes) value).asMap(),
|
||||
(Map<String, Object>) expected.get(key.getKey()));
|
||||
return;
|
||||
}
|
||||
assertThat(expected.get(key.getKey())).isEqualTo(value);
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void asAttributes(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
Attributes attributes = extendedAttributes.asAttributes();
|
||||
|
||||
attributes.forEach(
|
||||
(key, value) -> {
|
||||
assertThat(value).isEqualTo(expectedMap.get(key.getKey()));
|
||||
});
|
||||
|
||||
long expectedSize =
|
||||
expectedMap.values().stream().filter(value -> !(value instanceof Map)).count();
|
||||
assertThat(attributes.size()).isEqualTo(expectedSize);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void toBuilder(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
ExtendedAttributesBuilder builder = extendedAttributes.toBuilder();
|
||||
|
||||
builder.put("extraKey", "value");
|
||||
|
||||
ExtendedAttributes extendedAttributes1 = builder.build();
|
||||
assertThat(extendedAttributes1.size()).isEqualTo(expectedMap.size() + 1);
|
||||
|
||||
ExtendedAttributes extendedAttributes2 =
|
||||
extendedAttributes1.toBuilder().remove(ExtendedAttributeKey.stringKey("extraKey")).build();
|
||||
|
||||
assertThat(extendedAttributes2).isEqualTo(extendedAttributes);
|
||||
assertThat(extendedAttributes2.size()).isEqualTo(expectedMap.size());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("attributesArgs")
|
||||
void equalsAndHashcode(ExtendedAttributes extendedAttributes, Map<String, Object> expectedMap) {
|
||||
ExtendedAttributes withExtraEntry =
|
||||
extendedAttributes.toBuilder().put("extraKey", "value").build();
|
||||
assertThat(extendedAttributes).isNotEqualTo(withExtraEntry);
|
||||
assertThat(extendedAttributes.hashCode()).isNotEqualTo(withExtraEntry.hashCode());
|
||||
|
||||
ExtendedAttributes copy1 =
|
||||
extendedAttributes.toBuilder().remove(ExtendedAttributeKey.stringKey("extraKey")).build();
|
||||
assertThat(extendedAttributes).isEqualTo(copy1);
|
||||
assertThat(extendedAttributes.hashCode()).isEqualTo(copy1.hashCode());
|
||||
|
||||
ExtendedAttributes copy2 = fromMap(expectedMap);
|
||||
assertThat(extendedAttributes).isEqualTo(copy2);
|
||||
assertThat(extendedAttributes.hashCode()).isEqualTo(copy2.hashCode());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static ExtendedAttributes fromMap(Map<String, Object> map) {
|
||||
ExtendedAttributesBuilder builder = ExtendedAttributes.builder();
|
||||
map.forEach(
|
||||
(key, value) -> {
|
||||
ExtendedAttributeKey<?> extendedAttributeKey = getKey(key, value);
|
||||
if (extendedAttributeKey.getType() == ExtendedAttributeType.EXTENDED_ATTRIBUTES) {
|
||||
builder.put(
|
||||
(ExtendedAttributeKey<ExtendedAttributes>) extendedAttributeKey,
|
||||
fromMap((Map<String, Object>) value));
|
||||
return;
|
||||
}
|
||||
putInBuilder((ExtendedAttributeKey<Object>) extendedAttributeKey, value, builder);
|
||||
});
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static void putInBuilder(
|
||||
ExtendedAttributeKey<Object> key, Object value, ExtendedAttributesBuilder builder) {
|
||||
builder.put(key, value);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> attributesArgs() {
|
||||
return Stream.of(
|
||||
// Single entry attributes
|
||||
Arguments.of(ExtendedAttributes.builder().build(), Collections.emptyMap()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", "value").build(),
|
||||
ImmutableMap.builder().put("key", "value").build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", true).build(),
|
||||
ImmutableMap.builder().put("key", true).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", 1L).build(),
|
||||
ImmutableMap.builder().put("key", 1L).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", 1.1).build(),
|
||||
ImmutableMap.builder().put("key", 1.1).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", "value1", "value2").build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList("value1", "value2")).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", true, false).build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList(true, false)).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", 1L, 2L).build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList(1L, 2L)).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put("key", 1.1, 2.2).build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList(1.1, 2.2)).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put("key", ExtendedAttributes.builder().put("child", "value").build())
|
||||
.build(),
|
||||
ImmutableMap.builder()
|
||||
.put("key", ImmutableMap.builder().put("child", "value").build())
|
||||
.build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put(ExtendedAttributeKey.stringKey("key"), "value")
|
||||
.build(),
|
||||
ImmutableMap.builder().put("key", "value").build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put(ExtendedAttributeKey.booleanKey("key"), true).build(),
|
||||
ImmutableMap.builder().put("key", true).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put(ExtendedAttributeKey.longKey("key"), 1L).build(),
|
||||
ImmutableMap.builder().put("key", 1L).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder().put(ExtendedAttributeKey.doubleKey("key"), 1.1).build(),
|
||||
ImmutableMap.builder().put("key", 1.1).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put(ExtendedAttributeKey.stringArrayKey("key"), Arrays.asList("value1", "value2"))
|
||||
.build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList("value1", "value2")).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put(ExtendedAttributeKey.booleanArrayKey("key"), Arrays.asList(true, false))
|
||||
.build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList(true, false)).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put(ExtendedAttributeKey.longArrayKey("key"), Arrays.asList(1L, 2L))
|
||||
.build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList(1L, 2L)).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put(ExtendedAttributeKey.doubleArrayKey("key"), Arrays.asList(1.1, 2.2))
|
||||
.build(),
|
||||
ImmutableMap.builder().put("key", Arrays.asList(1.1, 2.2)).build()),
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put(
|
||||
ExtendedAttributeKey.extendedAttributesKey("key"),
|
||||
ExtendedAttributes.builder().put("child", "value").build())
|
||||
.build(),
|
||||
ImmutableMap.builder()
|
||||
.put("key", ImmutableMap.builder().put("child", "value").build())
|
||||
.build()),
|
||||
// Multiple entries
|
||||
Arguments.of(
|
||||
ExtendedAttributes.builder()
|
||||
.put("key1", "value1")
|
||||
.put("key2", "value2")
|
||||
.put("key3", true)
|
||||
.put("key4", 1L)
|
||||
.put("key5", 1.1)
|
||||
.put("key6", "value1", "value2")
|
||||
.put("key7", true, false)
|
||||
.put("key8", 1L, 2L)
|
||||
.put("key9", 1.1, 2.2)
|
||||
.put("key10", ExtendedAttributes.builder().put("child", "value").build())
|
||||
.build(),
|
||||
ImmutableMap.builder()
|
||||
.put("key1", "value1")
|
||||
.put("key2", "value2")
|
||||
.put("key3", true)
|
||||
.put("key4", 1L)
|
||||
.put("key5", 1.1)
|
||||
.put("key6", Arrays.asList("value1", "value2"))
|
||||
.put("key7", Arrays.asList(true, false))
|
||||
.put("key8", Arrays.asList(1L, 2L))
|
||||
.put("key9", Arrays.asList(1.1, 2.2))
|
||||
.put("key10", ImmutableMap.builder().put("child", "value").build())
|
||||
.build()));
|
||||
}
|
||||
|
||||
private static Map<String, Object> toMap(ExtendedAttributes extendedAttributes) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
extendedAttributes.forEach(
|
||||
(key, value) -> {
|
||||
if (key.getType() == ExtendedAttributeType.EXTENDED_ATTRIBUTES) {
|
||||
map.put(key.getKey(), toMap((ExtendedAttributes) value));
|
||||
return;
|
||||
}
|
||||
map.put(key.getKey(), value);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ExtendedAttributeKey<?> getKey(String key, Object value) {
|
||||
switch (getType(value)) {
|
||||
case STRING:
|
||||
return ExtendedAttributeKey.stringKey(key);
|
||||
case BOOLEAN:
|
||||
return ExtendedAttributeKey.booleanKey(key);
|
||||
case LONG:
|
||||
return ExtendedAttributeKey.longKey(key);
|
||||
case DOUBLE:
|
||||
return ExtendedAttributeKey.doubleKey(key);
|
||||
case STRING_ARRAY:
|
||||
return ExtendedAttributeKey.stringArrayKey(key);
|
||||
case BOOLEAN_ARRAY:
|
||||
return ExtendedAttributeKey.booleanArrayKey(key);
|
||||
case LONG_ARRAY:
|
||||
return ExtendedAttributeKey.longArrayKey(key);
|
||||
case DOUBLE_ARRAY:
|
||||
return ExtendedAttributeKey.doubleArrayKey(key);
|
||||
case EXTENDED_ATTRIBUTES:
|
||||
return ExtendedAttributeKey.extendedAttributesKey(key);
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static ExtendedAttributeType getType(Object value) {
|
||||
if (value instanceof String) {
|
||||
return ExtendedAttributeType.STRING;
|
||||
}
|
||||
if (value instanceof Boolean) {
|
||||
return ExtendedAttributeType.BOOLEAN;
|
||||
}
|
||||
if ((value instanceof Long) || (value instanceof Integer)) {
|
||||
return ExtendedAttributeType.LONG;
|
||||
}
|
||||
if ((value instanceof Double) || (value instanceof Float)) {
|
||||
return ExtendedAttributeType.DOUBLE;
|
||||
}
|
||||
if (value instanceof List) {
|
||||
List<Object> list = (List<Object>) value;
|
||||
if (list.isEmpty()) {
|
||||
throw new IllegalArgumentException("Empty list");
|
||||
}
|
||||
if (list.get(0) instanceof String) {
|
||||
return ExtendedAttributeType.STRING_ARRAY;
|
||||
}
|
||||
if (list.get(0) instanceof Boolean) {
|
||||
return ExtendedAttributeType.BOOLEAN_ARRAY;
|
||||
}
|
||||
if ((list.get(0) instanceof Long) || (list.get(0) instanceof Integer)) {
|
||||
return ExtendedAttributeType.LONG_ARRAY;
|
||||
}
|
||||
if ((list.get(0) instanceof Double) || (list.get(0) instanceof Float)) {
|
||||
return ExtendedAttributeType.DOUBLE_ARRAY;
|
||||
}
|
||||
}
|
||||
if ((value instanceof Map)) {
|
||||
return ExtendedAttributeType.EXTENDED_ATTRIBUTES;
|
||||
}
|
||||
throw new IllegalArgumentException("Unrecognized value type: " + value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class GlobalConfigProviderTest {
|
||||
|
||||
@BeforeAll
|
||||
static void beforeClass() {
|
||||
GlobalConfigProvider.resetForTest();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void after() {
|
||||
GlobalConfigProvider.resetForTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void setAndGet() {
|
||||
assertThat(GlobalConfigProvider.get()).isEqualTo(ConfigProvider.noop());
|
||||
ConfigProvider configProvider = DeclarativeConfigProperties::empty;
|
||||
GlobalConfigProvider.set(configProvider);
|
||||
assertThat(GlobalConfigProvider.get()).isSameAs(configProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setThenSet() {
|
||||
ConfigProvider configProvider = DeclarativeConfigProperties::empty;
|
||||
GlobalConfigProvider.set(configProvider);
|
||||
assertThatThrownBy(() -> GlobalConfigProvider.set(configProvider))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("GlobalConfigProvider.set has already been called")
|
||||
.hasStackTraceContaining("setThenSet");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.YamlDeclarativeConfigProperties;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class InstrumentationConfigUtilTest {
|
||||
|
||||
/**
|
||||
* See <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-configuration/blob/main/examples/kitchen-sink.yaml">kitchen-sink.yaml</a>.
|
||||
*/
|
||||
private static final String kitchenSinkInstrumentationConfig =
|
||||
"instrumentation/development:\n"
|
||||
+ " general:\n"
|
||||
+ " peer:\n"
|
||||
+ " service_mapping:\n"
|
||||
+ " - peer: 1.2.3.4\n"
|
||||
+ " service: FooService\n"
|
||||
+ " - peer: 2.3.4.5\n"
|
||||
+ " service: BarService\n"
|
||||
+ " http:\n"
|
||||
+ " client:\n"
|
||||
+ " request_captured_headers:\n"
|
||||
+ " - client-request-header1\n"
|
||||
+ " - client-request-header2\n"
|
||||
+ " response_captured_headers:\n"
|
||||
+ " - client-response-header1\n"
|
||||
+ " - client-response-header2\n"
|
||||
+ " server:\n"
|
||||
+ " request_captured_headers:\n"
|
||||
+ " - server-request-header1\n"
|
||||
+ " - server-request-header2\n"
|
||||
+ " response_captured_headers:\n"
|
||||
+ " - server-response-header1\n"
|
||||
+ " - server-response-header2\n"
|
||||
+ " java:\n"
|
||||
+ " example:\n"
|
||||
+ " property: \"value\"";
|
||||
|
||||
private static final ConfigProvider kitchenSinkConfigProvider =
|
||||
toConfigProvider(kitchenSinkInstrumentationConfig);
|
||||
private static final ConfigProvider emptyInstrumentationConfigProvider =
|
||||
toConfigProvider("instrumentation/development:\n");
|
||||
private static final ConfigProvider emptyGeneralConfigProvider =
|
||||
toConfigProvider("instrumentation/development:\n general:\n");
|
||||
private static final ConfigProvider emptyHttpConfigProvider =
|
||||
toConfigProvider("instrumentation/development:\n general:\n http:\n");
|
||||
|
||||
private static ConfigProvider toConfigProvider(String configYaml) {
|
||||
OpenTelemetryConfigurationModel configuration =
|
||||
DeclarativeConfiguration.parse(
|
||||
new ByteArrayInputStream(configYaml.getBytes(StandardCharsets.UTF_8)));
|
||||
return SdkConfigProvider.create(configuration);
|
||||
}
|
||||
|
||||
@Test
|
||||
void peerServiceMapping() {
|
||||
assertThat(InstrumentationConfigUtil.peerServiceMapping(kitchenSinkConfigProvider))
|
||||
.isEqualTo(ImmutableMap.of("1.2.3.4", "FooService", "2.3.4.5", "BarService"));
|
||||
assertThat(InstrumentationConfigUtil.peerServiceMapping(emptyInstrumentationConfigProvider))
|
||||
.isNull();
|
||||
assertThat(InstrumentationConfigUtil.peerServiceMapping(emptyGeneralConfigProvider)).isNull();
|
||||
assertThat(InstrumentationConfigUtil.peerServiceMapping(emptyHttpConfigProvider)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpClientRequestCapturedHeaders() {
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpClientRequestCapturedHeaders(kitchenSinkConfigProvider))
|
||||
.isEqualTo(Arrays.asList("client-request-header1", "client-request-header2"));
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpClientRequestCapturedHeaders(
|
||||
emptyInstrumentationConfigProvider))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpClientRequestCapturedHeaders(emptyGeneralConfigProvider))
|
||||
.isNull();
|
||||
assertThat(InstrumentationConfigUtil.httpClientRequestCapturedHeaders(emptyHttpConfigProvider))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpClientResponseCapturedHeaders() {
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpClientResponseCapturedHeaders(kitchenSinkConfigProvider))
|
||||
.isEqualTo(Arrays.asList("client-response-header1", "client-response-header2"));
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpClientResponseCapturedHeaders(
|
||||
emptyInstrumentationConfigProvider))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpClientResponseCapturedHeaders(emptyGeneralConfigProvider))
|
||||
.isNull();
|
||||
assertThat(InstrumentationConfigUtil.httpClientResponseCapturedHeaders(emptyHttpConfigProvider))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpServerRequestCapturedHeaders() {
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpServerRequestCapturedHeaders(kitchenSinkConfigProvider))
|
||||
.isEqualTo(Arrays.asList("server-request-header1", "server-request-header2"));
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpServerRequestCapturedHeaders(
|
||||
emptyInstrumentationConfigProvider))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpServerRequestCapturedHeaders(emptyGeneralConfigProvider))
|
||||
.isNull();
|
||||
assertThat(InstrumentationConfigUtil.httpServerRequestCapturedHeaders(emptyHttpConfigProvider))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpServerResponseCapturedHeaders() {
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpServerResponseCapturedHeaders(kitchenSinkConfigProvider))
|
||||
.isEqualTo(Arrays.asList("server-response-header1", "server-response-header2"));
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpServerResponseCapturedHeaders(
|
||||
emptyInstrumentationConfigProvider))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.httpServerResponseCapturedHeaders(emptyGeneralConfigProvider))
|
||||
.isNull();
|
||||
assertThat(InstrumentationConfigUtil.httpServerResponseCapturedHeaders(emptyHttpConfigProvider))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void javaInstrumentationConfig() {
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.javaInstrumentationConfig(
|
||||
kitchenSinkConfigProvider, "example"))
|
||||
.isNotNull()
|
||||
.isInstanceOfSatisfying(
|
||||
YamlDeclarativeConfigProperties.class,
|
||||
exampleConfig ->
|
||||
assertThat(DeclarativeConfigProperties.toMap(exampleConfig))
|
||||
.isEqualTo(ImmutableMap.of("property", "value")));
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.javaInstrumentationConfig(kitchenSinkConfigProvider, "foo"))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.javaInstrumentationConfig(
|
||||
emptyInstrumentationConfigProvider, "example"))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.javaInstrumentationConfig(
|
||||
emptyGeneralConfigProvider, "example"))
|
||||
.isNull();
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.javaInstrumentationConfig(emptyHttpConfigProvider, "example"))
|
||||
.isNull();
|
||||
}
|
||||
}
|
|
@ -10,7 +10,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import io.opentelemetry.api.common.Value;
|
||||
import io.opentelemetry.api.logs.Logger;
|
||||
import io.opentelemetry.api.logs.LoggerProvider;
|
||||
import io.opentelemetry.api.logs.Severity;
|
||||
import io.opentelemetry.api.testing.internal.AbstractDefaultLoggerTest;
|
||||
import io.opentelemetry.context.Context;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ExtendedDefaultLoggerTest extends AbstractDefaultLoggerTest {
|
||||
|
@ -26,10 +28,18 @@ class ExtendedDefaultLoggerTest extends AbstractDefaultLoggerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // testing deprecated code
|
||||
void incubatingApiIsLoaded() {
|
||||
Logger logger = LoggerProvider.noop().get("test");
|
||||
|
||||
assertThat(logger).isInstanceOf(ExtendedLogger.class);
|
||||
assertThat(logger)
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedLogger.class,
|
||||
extendedLogger -> {
|
||||
assertThat(extendedLogger.isEnabled(Severity.ERROR, Context.current())).isFalse();
|
||||
assertThat(extendedLogger.isEnabled(Severity.ERROR)).isFalse();
|
||||
assertThat(extendedLogger.isEnabled()).isFalse();
|
||||
});
|
||||
ExtendedLogRecordBuilder builder = (ExtendedLogRecordBuilder) logger.logRecordBuilder();
|
||||
assertThat(builder).isInstanceOf(ExtendedLogRecordBuilder.class);
|
||||
assertThat(builder.setBody(Value.of(0))).isSameAs(builder);
|
||||
|
|
|
@ -9,19 +9,31 @@ import static io.opentelemetry.sdk.internal.ScopeConfiguratorBuilder.nameEquals;
|
|||
import static io.opentelemetry.sdk.logs.internal.LoggerConfig.disabled;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributeKey;
|
||||
import io.opentelemetry.api.incubator.common.ExtendedAttributes;
|
||||
import io.opentelemetry.api.logs.Logger;
|
||||
import io.opentelemetry.api.logs.Severity;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
||||
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.internal.ExtendedLogRecordData;
|
||||
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
|
||||
import io.opentelemetry.sdk.logs.internal.SdkLoggerProviderUtil;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Demonstrating usage of extended Logs Bridge API. */
|
||||
class ExtendedLogsBridgeApiUsageTest {
|
||||
|
||||
private static final java.util.logging.Logger logger =
|
||||
java.util.logging.Logger.getLogger(ExtendedLogsBridgeApiUsageTest.class.getName());
|
||||
|
||||
@Test
|
||||
void loggerEnabled() {
|
||||
// Setup SdkLoggerProvider
|
||||
|
@ -42,24 +54,26 @@ class ExtendedLogsBridgeApiUsageTest {
|
|||
ExtendedLogger loggerB = (ExtendedLogger) loggerProvider.get("loggerB");
|
||||
|
||||
// Check if logger is enabled before emitting log and avoid unnecessary computation
|
||||
if (loggerA.isEnabled()) {
|
||||
if (loggerA.isEnabled(Severity.INFO)) {
|
||||
loggerA
|
||||
.logRecordBuilder()
|
||||
.setSeverity(Severity.INFO)
|
||||
.setBody("hello world!")
|
||||
.setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
|
||||
.emit();
|
||||
}
|
||||
if (loggerB.isEnabled()) {
|
||||
if (loggerB.isEnabled(Severity.INFO)) {
|
||||
loggerB
|
||||
.logRecordBuilder()
|
||||
.setSeverity(Severity.INFO)
|
||||
.setBody("hello world!")
|
||||
.setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
|
||||
.emit();
|
||||
}
|
||||
|
||||
// loggerA is enabled, loggerB is disabled
|
||||
assertThat(loggerA.isEnabled()).isTrue();
|
||||
assertThat(loggerB.isEnabled()).isFalse();
|
||||
assertThat(loggerA.isEnabled(Severity.INFO)).isTrue();
|
||||
assertThat(loggerB.isEnabled(Severity.INFO)).isFalse();
|
||||
|
||||
// Collected data only consists of logs from loggerA. Note, loggerB's logs would be
|
||||
// omitted from the results even if logs were emitted. The check if enabled simply avoids
|
||||
|
@ -76,4 +90,148 @@ class ExtendedLogsBridgeApiUsageTest {
|
|||
private static String flipCoin() {
|
||||
return random.nextBoolean() ? "heads" : "tails";
|
||||
}
|
||||
|
||||
// Primitive keys
|
||||
AttributeKey<String> strKey = AttributeKey.stringKey("acme.string");
|
||||
AttributeKey<Long> longKey = AttributeKey.longKey("acme.long");
|
||||
AttributeKey<Boolean> booleanKey = AttributeKey.booleanKey("acme.boolean");
|
||||
AttributeKey<Double> doubleKey = AttributeKey.doubleKey("acme.double");
|
||||
|
||||
// Primitive array keys
|
||||
AttributeKey<List<String>> strArrKey = AttributeKey.stringArrayKey("acme.string_array");
|
||||
AttributeKey<List<Long>> longArrKey = AttributeKey.longArrayKey("acme.long_array");
|
||||
AttributeKey<List<Boolean>> booleanArrKey = AttributeKey.booleanArrayKey("acme.boolean_array");
|
||||
AttributeKey<List<Double>> doubleArrKey = AttributeKey.doubleArrayKey("acme.double_array");
|
||||
|
||||
// Extended keys
|
||||
ExtendedAttributeKey<ExtendedAttributes> mapKey =
|
||||
ExtendedAttributeKey.extendedAttributesKey("acme.map");
|
||||
|
||||
@Test
|
||||
@SuppressLogger(ExtendedLogsBridgeApiUsageTest.class)
|
||||
void extendedAttributesUsage() {
|
||||
// Initialize from builder. Varargs style initialization (ExtendedAttributes.of(...) not
|
||||
// supported.
|
||||
ExtendedAttributes extendedAttributes =
|
||||
ExtendedAttributes.builder()
|
||||
.put(strKey, "value")
|
||||
.put(longKey, 1L)
|
||||
.put(booleanKey, true)
|
||||
.put(doubleKey, 1.1)
|
||||
.put(strArrKey, Arrays.asList("value1", "value2"))
|
||||
.put(longArrKey, Arrays.asList(1L, 2L))
|
||||
.put(booleanArrKey, Arrays.asList(true, false))
|
||||
.put(doubleArrKey, Arrays.asList(1.1, 2.2))
|
||||
.put(
|
||||
mapKey,
|
||||
ExtendedAttributes.builder().put("childStr", "value").put("childLong", 1L).build())
|
||||
.build();
|
||||
|
||||
// Retrieval
|
||||
assertThat(extendedAttributes.get(strKey)).isEqualTo("value");
|
||||
assertThat(extendedAttributes.get(longKey)).isEqualTo(1);
|
||||
assertThat(extendedAttributes.get(booleanKey)).isEqualTo(true);
|
||||
assertThat(extendedAttributes.get(doubleKey)).isEqualTo(1.1);
|
||||
assertThat(extendedAttributes.get(strArrKey)).isEqualTo(Arrays.asList("value1", "value2"));
|
||||
assertThat(extendedAttributes.get(longArrKey)).isEqualTo(Arrays.asList(1L, 2L));
|
||||
assertThat(extendedAttributes.get(booleanArrKey)).isEqualTo(Arrays.asList(true, false));
|
||||
assertThat(extendedAttributes.get(doubleArrKey)).isEqualTo(Arrays.asList(1.1, 2.2));
|
||||
assertThat(extendedAttributes.get(mapKey))
|
||||
.isEqualTo(
|
||||
ExtendedAttributes.builder().put("childStr", "value").put("childLong", 1L).build());
|
||||
|
||||
// Iteration
|
||||
// Output:
|
||||
// acme.boolean(BOOLEAN): true
|
||||
// acme.boolean_array(BOOLEAN_ARRAY): [true, false]
|
||||
// acme.double(DOUBLE): 1.1
|
||||
// acme.double_array(DOUBLE_ARRAY): [1.1, 2.2]
|
||||
// acme.long(LONG): 1
|
||||
// acme.long_array(LONG_ARRAY): [1, 2]
|
||||
// acme.map(EXTENDED_ATTRIBUTES): {childLong=1, childStr="value"}
|
||||
// acme.string(STRING): value
|
||||
// acme.string_array(STRING_ARRAY): [value1, value2]
|
||||
extendedAttributes.forEach(
|
||||
(extendedAttributeKey, object) ->
|
||||
logger.info(
|
||||
String.format(
|
||||
"%s(%s): %s",
|
||||
extendedAttributeKey.getKey(), extendedAttributeKey.getType(), object)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // testing deprecated code
|
||||
void logRecordBuilder_ExtendedAttributes() {
|
||||
InMemoryLogRecordExporter exporter = InMemoryLogRecordExporter.create();
|
||||
SdkLoggerProvider loggerProvider =
|
||||
SdkLoggerProvider.builder()
|
||||
.addLogRecordProcessor(SimpleLogRecordProcessor.create(exporter))
|
||||
.build();
|
||||
|
||||
Logger logger = loggerProvider.get("logger");
|
||||
|
||||
// Can set either standard or extended attributes on
|
||||
((ExtendedLogRecordBuilder) logger.logRecordBuilder())
|
||||
.setBody("message")
|
||||
.setAttribute(strKey, "value")
|
||||
.setAttribute(longKey, 1L)
|
||||
.setAttribute(booleanKey, true)
|
||||
.setAttribute(doubleKey, 1.1)
|
||||
.setAttribute(strArrKey, Arrays.asList("value1", "value2"))
|
||||
.setAttribute(longArrKey, Arrays.asList(1L, 2L))
|
||||
.setAttribute(booleanArrKey, Arrays.asList(true, false))
|
||||
.setAttribute(doubleArrKey, Arrays.asList(1.1, 2.2))
|
||||
.setAttribute(
|
||||
mapKey,
|
||||
ExtendedAttributes.builder().put("childStr", "value").put("childLong", 1L).build())
|
||||
.setAllAttributes(Attributes.builder().put("key1", "value").build())
|
||||
.setAllAttributes(ExtendedAttributes.builder().put("key2", "value").build())
|
||||
.emit();
|
||||
|
||||
assertThat(exporter.getFinishedLogRecordItems())
|
||||
.satisfiesExactly(
|
||||
logRecordData -> {
|
||||
assertThat(logRecordData).isInstanceOf(ExtendedLogRecordData.class);
|
||||
ExtendedLogRecordData extendedLogRecordData = (ExtendedLogRecordData) logRecordData;
|
||||
|
||||
// Optionally access standard attributes, which filters out any extended attribute
|
||||
// types
|
||||
assertThat(extendedLogRecordData.getAttributes())
|
||||
.isEqualTo(
|
||||
Attributes.builder()
|
||||
.put(strKey, "value")
|
||||
.put(longKey, 1L)
|
||||
.put(booleanKey, true)
|
||||
.put(doubleKey, 1.1)
|
||||
.put(strArrKey, Arrays.asList("value1", "value2"))
|
||||
.put(longArrKey, Arrays.asList(1L, 2L))
|
||||
.put(booleanArrKey, Arrays.asList(true, false))
|
||||
.put(doubleArrKey, Arrays.asList(1.1, 2.2))
|
||||
.put("key1", "value")
|
||||
.put("key2", "value")
|
||||
.build());
|
||||
|
||||
// But preferably access and serialize full extended attributes
|
||||
assertThat(extendedLogRecordData.getExtendedAttributes())
|
||||
.isEqualTo(
|
||||
ExtendedAttributes.builder()
|
||||
.put(strKey, "value")
|
||||
.put(longKey, 1L)
|
||||
.put(booleanKey, true)
|
||||
.put(doubleKey, 1.1)
|
||||
.put(strArrKey, Arrays.asList("value1", "value2"))
|
||||
.put(longArrKey, Arrays.asList(1L, 2L))
|
||||
.put(booleanArrKey, Arrays.asList(true, false))
|
||||
.put(doubleArrKey, Arrays.asList(1.1, 2.2))
|
||||
.put(
|
||||
mapKey,
|
||||
ExtendedAttributes.builder()
|
||||
.put("childStr", "value")
|
||||
.put("childLong", 1L)
|
||||
.build())
|
||||
.put("key1", "value")
|
||||
.put("key2", "value")
|
||||
.build());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import io.opentelemetry.api.OpenTelemetry;
|
|||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.api.testing.internal.AbstractDefaultMeterTest;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ExtendedDefaultMeterTest extends AbstractDefaultMeterTest {
|
||||
|
@ -27,44 +26,53 @@ class ExtendedDefaultMeterTest extends AbstractDefaultMeterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void incubatingApiIsLoaded() {
|
||||
void incubatingApiIsLoaded() {
|
||||
Meter meter = MeterProvider.noop().get("test");
|
||||
assertThat(meter).isSameAs(OpenTelemetry.noop().getMeter("test"));
|
||||
|
||||
Assertions.assertThat(meter.gaugeBuilder("test").ofLongs())
|
||||
.isInstanceOf(ExtendedLongGaugeBuilder.class);
|
||||
Assertions.assertThat(meter.gaugeBuilder("test").ofLongs().build())
|
||||
.isInstanceOf(ExtendedLongGauge.class);
|
||||
Assertions.assertThat(meter.gaugeBuilder("test"))
|
||||
.isInstanceOf(ExtendedDoubleGaugeBuilder.class);
|
||||
Assertions.assertThat(meter.gaugeBuilder("test").build())
|
||||
.isInstanceOf(ExtendedDoubleGauge.class);
|
||||
assertThat(meter.gaugeBuilder("test").ofLongs()).isInstanceOf(ExtendedLongGaugeBuilder.class);
|
||||
assertThat(meter.gaugeBuilder("test").ofLongs().build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedLongGauge.class, instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
assertThat(meter.gaugeBuilder("test")).isInstanceOf(ExtendedDoubleGaugeBuilder.class);
|
||||
assertThat(meter.gaugeBuilder("test").build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedDoubleGauge.class, instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
|
||||
Assertions.assertThat(meter.histogramBuilder("test").ofLongs())
|
||||
assertThat(meter.histogramBuilder("test").ofLongs())
|
||||
.isInstanceOf(ExtendedLongHistogramBuilder.class);
|
||||
Assertions.assertThat(meter.histogramBuilder("test").ofLongs().build())
|
||||
.isInstanceOf(ExtendedLongHistogram.class);
|
||||
Assertions.assertThat(meter.histogramBuilder("test"))
|
||||
.isInstanceOf(ExtendedDoubleHistogramBuilder.class);
|
||||
Assertions.assertThat(meter.histogramBuilder("test").build())
|
||||
.isInstanceOf(ExtendedDoubleHistogram.class);
|
||||
assertThat(meter.histogramBuilder("test").ofLongs().build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedLongHistogram.class,
|
||||
instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
assertThat(meter.histogramBuilder("test")).isInstanceOf(ExtendedDoubleHistogramBuilder.class);
|
||||
assertThat(meter.histogramBuilder("test").build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedDoubleHistogram.class,
|
||||
instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
|
||||
Assertions.assertThat(meter.counterBuilder("test"))
|
||||
.isInstanceOf(ExtendedLongCounterBuilder.class);
|
||||
Assertions.assertThat(meter.counterBuilder("test").build())
|
||||
.isInstanceOf(ExtendedLongCounter.class);
|
||||
Assertions.assertThat(meter.counterBuilder("test").ofDoubles())
|
||||
assertThat(meter.counterBuilder("test")).isInstanceOf(ExtendedLongCounterBuilder.class);
|
||||
assertThat(meter.counterBuilder("test").build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedLongCounter.class, instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
assertThat(meter.counterBuilder("test").ofDoubles())
|
||||
.isInstanceOf(ExtendedDoubleCounterBuilder.class);
|
||||
Assertions.assertThat(meter.counterBuilder("test").ofDoubles().build())
|
||||
.isInstanceOf(ExtendedDoubleCounter.class);
|
||||
assertThat(meter.counterBuilder("test").ofDoubles().build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedDoubleCounter.class,
|
||||
instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
|
||||
Assertions.assertThat(meter.upDownCounterBuilder("test"))
|
||||
assertThat(meter.upDownCounterBuilder("test"))
|
||||
.isInstanceOf(ExtendedLongUpDownCounterBuilder.class);
|
||||
Assertions.assertThat(meter.upDownCounterBuilder("test").build())
|
||||
.isInstanceOf(ExtendedLongUpDownCounter.class);
|
||||
Assertions.assertThat(meter.upDownCounterBuilder("test").ofDoubles())
|
||||
assertThat(meter.upDownCounterBuilder("test").build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedLongUpDownCounter.class,
|
||||
instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
assertThat(meter.upDownCounterBuilder("test").ofDoubles())
|
||||
.isInstanceOf(ExtendedDoubleUpDownCounterBuilder.class);
|
||||
Assertions.assertThat(meter.upDownCounterBuilder("test").ofDoubles().build())
|
||||
.isInstanceOf(ExtendedDoubleUpDownCounter.class);
|
||||
assertThat(meter.upDownCounterBuilder("test").ofDoubles().build())
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedDoubleUpDownCounter.class,
|
||||
instrument -> assertThat(instrument.isEnabled()).isFalse());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
package io.opentelemetry.api.incubator.trace;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.testing.internal.AbstractDefaultTracerTest;
|
||||
|
@ -27,17 +29,20 @@ class ExtendedDefaultTracerTest extends AbstractDefaultTracerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void incubatingApiIsLoaded() {
|
||||
void incubatingApiIsLoaded() {
|
||||
Tracer tracer = TracerProvider.noop().get("test");
|
||||
assertThat(tracer).isSameAs(OpenTelemetry.noop().getTracer("test"));
|
||||
|
||||
assertThat(tracer).isInstanceOf(ExtendedTracer.class);
|
||||
assertThat(tracer)
|
||||
.isInstanceOfSatisfying(
|
||||
ExtendedTracer.class,
|
||||
extendedTracer -> assertThat(extendedTracer.isEnabled()).isFalse());
|
||||
assertThat(tracer.spanBuilder("test")).isInstanceOf(ExtendedSpanBuilder.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void incubatingApi() {
|
||||
void incubatingApi() {
|
||||
ExtendedSpanBuilder spanBuilder =
|
||||
(ExtendedSpanBuilder) ExtendedDefaultTracer.getNoop().spanBuilder("test");
|
||||
assertThat(spanBuilder.setParentFrom(null, null)).isSameAs(spanBuilder);
|
||||
|
@ -45,21 +50,21 @@ class ExtendedDefaultTracerTest extends AbstractDefaultTracerTest {
|
|||
SpanRunnable<RuntimeException> spanRunnable = Mockito.mock(SpanRunnable.class);
|
||||
|
||||
spanBuilder.startAndRun(spanRunnable);
|
||||
Mockito.verify(spanRunnable).runInSpan();
|
||||
Mockito.reset(spanRunnable);
|
||||
verify(spanRunnable).runInSpan();
|
||||
reset(spanRunnable);
|
||||
|
||||
spanBuilder.startAndRun(spanRunnable, null);
|
||||
Mockito.verify(spanRunnable).runInSpan();
|
||||
Mockito.reset(spanRunnable);
|
||||
verify(spanRunnable).runInSpan();
|
||||
reset(spanRunnable);
|
||||
|
||||
SpanCallable<String, RuntimeException> spanCallable = Mockito.mock(SpanCallable.class);
|
||||
|
||||
spanBuilder.startAndCall(spanCallable);
|
||||
Mockito.verify(spanCallable).callInSpan();
|
||||
Mockito.reset(spanCallable);
|
||||
verify(spanCallable).callInSpan();
|
||||
reset(spanCallable);
|
||||
|
||||
spanBuilder.startAndCall(spanCallable, null);
|
||||
Mockito.verify(spanCallable).callInSpan();
|
||||
Mockito.reset(spanCallable);
|
||||
verify(spanCallable).callInSpan();
|
||||
reset(spanCallable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.api.incubator;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.opentelemetry.api.incubator.config.ConfigProvider;
|
||||
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
|
||||
import io.opentelemetry.api.incubator.config.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalLanguageSpecificInstrumentationModel;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class InstrumentationConfigUtilTest {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void toMap_RoundTrip() throws JsonProcessingException {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("string", "val");
|
||||
map.put("boolean", true);
|
||||
map.put("long", 1L);
|
||||
map.put("double", 1.1);
|
||||
map.put("null", null);
|
||||
map.put("stringList", Arrays.asList("val1", "val2"));
|
||||
map.put("boolList", Arrays.asList(true, false));
|
||||
map.put("longList", Arrays.asList(1L, 2L));
|
||||
map.put("doubleList", Arrays.asList(1.1d, 2.2d));
|
||||
map.put(
|
||||
"structuredList", Collections.singletonList(Collections.singletonMap("childKey", "val")));
|
||||
map.put("emptyList", Collections.emptyList());
|
||||
map.put("structured", Collections.singletonMap("childKey", "val"));
|
||||
map.put("emptyStructured", Collections.emptyMap());
|
||||
|
||||
String mapJson = MAPPER.writeValueAsString(map);
|
||||
DeclarativeConfigProperties properties =
|
||||
DeclarativeConfiguration.toConfigProperties(
|
||||
new ByteArrayInputStream(mapJson.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
assertThat(DeclarativeConfigProperties.toMap(properties)).isEqualTo(map);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstrumentationConfigModel_UnsetConfig() {
|
||||
ConfigProvider configProvider = () -> null;
|
||||
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.getInstrumentationConfigModel(
|
||||
configProvider, "my_instrumentation_library", MAPPER, Model.class))
|
||||
.isEqualTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstrumentationConfigModel_EmptyConfig() {
|
||||
ConfigProvider configProvider =
|
||||
withInstrumentationConfig("my_instrumentation_library", Collections.emptyMap());
|
||||
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.getInstrumentationConfigModel(
|
||||
configProvider, "my_instrumentation_library", MAPPER, Model.class))
|
||||
.isEqualTo(new Model());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInstrumentationConfigModel_KitchenSink() {
|
||||
ConfigProvider configProvider =
|
||||
withInstrumentationConfig(
|
||||
"my_instrumentation_library",
|
||||
ImmutableMap.<String, Object>builder()
|
||||
.put("string_property", "value")
|
||||
.put("boolean_property", true)
|
||||
.put("long_property", 1L)
|
||||
.put("double_property", 1.1d)
|
||||
.put("string_list_property", Arrays.asList("val1", "val2"))
|
||||
.put("boolean_list_property", Arrays.asList(true, false))
|
||||
.put("long_list_property", Arrays.asList(1L, 2L))
|
||||
.put("double_list_property", Arrays.asList(1.1d, 2.2d))
|
||||
.put("map_property", Collections.singletonMap("childKey", "val"))
|
||||
.put(
|
||||
"structured_list_property",
|
||||
Collections.singletonList(
|
||||
ImmutableMap.of("key", "the_key", "value", "the_value")))
|
||||
.build());
|
||||
|
||||
Model expected = new Model();
|
||||
expected.stringProperty = "value";
|
||||
expected.booleanProperty = true;
|
||||
expected.longProperty = 1L;
|
||||
expected.doubleProperty = 1.1d;
|
||||
expected.stringListProperty = Arrays.asList("val1", "val2");
|
||||
expected.booleanListProperty = Arrays.asList(true, false);
|
||||
expected.longListProperty = Arrays.asList(1L, 2L);
|
||||
expected.doubleListProperty = Arrays.asList(1.1d, 2.2d);
|
||||
expected.mapProperty = Collections.singletonMap("childKey", "val");
|
||||
ListEntryModel listEntryModel = new ListEntryModel();
|
||||
listEntryModel.key = "the_key";
|
||||
listEntryModel.value = "the_value";
|
||||
expected.structuredListProperty = Collections.singletonList(listEntryModel);
|
||||
|
||||
assertThat(
|
||||
InstrumentationConfigUtil.getInstrumentationConfigModel(
|
||||
configProvider, "my_instrumentation_library", MAPPER, Model.class))
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
private static ConfigProvider withInstrumentationConfig(
|
||||
String instrumentationName, Map<String, Object> instrumentationConfig) {
|
||||
ExperimentalLanguageSpecificInstrumentationModel javaConfig =
|
||||
new ExperimentalLanguageSpecificInstrumentationModel();
|
||||
javaConfig.setAdditionalProperty(instrumentationName, instrumentationConfig);
|
||||
|
||||
return SdkConfigProvider.create(
|
||||
new OpenTelemetryConfigurationModel()
|
||||
.withInstrumentationDevelopment(new InstrumentationModel().withJava(javaConfig)));
|
||||
}
|
||||
|
||||
private static class Model {
|
||||
@JsonProperty("string_property")
|
||||
private String stringProperty;
|
||||
|
||||
@JsonProperty("boolean_property")
|
||||
private Boolean booleanProperty;
|
||||
|
||||
@JsonProperty("long_property")
|
||||
private Long longProperty;
|
||||
|
||||
@JsonProperty("double_property")
|
||||
private Double doubleProperty;
|
||||
|
||||
@JsonProperty("string_list_property")
|
||||
private List<String> stringListProperty;
|
||||
|
||||
@JsonProperty("boolean_list_property")
|
||||
private List<Boolean> booleanListProperty;
|
||||
|
||||
@JsonProperty("long_list_property")
|
||||
private List<Long> longListProperty;
|
||||
|
||||
@JsonProperty("double_list_property")
|
||||
private List<Double> doubleListProperty;
|
||||
|
||||
;
|
||||
|
||||
@JsonProperty("map_property")
|
||||
private Map<String, Object> mapProperty;
|
||||
|
||||
@JsonProperty("structured_list_property")
|
||||
private List<ListEntryModel> structuredListProperty;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Model)) {
|
||||
return false;
|
||||
}
|
||||
Model model = (Model) o;
|
||||
return Objects.equals(stringProperty, model.stringProperty)
|
||||
&& Objects.equals(booleanProperty, model.booleanProperty)
|
||||
&& Objects.equals(longProperty, model.longProperty)
|
||||
&& Objects.equals(doubleProperty, model.doubleProperty)
|
||||
&& Objects.equals(stringListProperty, model.stringListProperty)
|
||||
&& Objects.equals(booleanListProperty, model.booleanListProperty)
|
||||
&& Objects.equals(longListProperty, model.longListProperty)
|
||||
&& Objects.equals(doubleListProperty, model.doubleListProperty)
|
||||
&& Objects.equals(mapProperty, model.mapProperty)
|
||||
&& Objects.equals(structuredListProperty, model.structuredListProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
stringProperty,
|
||||
booleanProperty,
|
||||
longProperty,
|
||||
doubleProperty,
|
||||
stringListProperty,
|
||||
booleanListProperty,
|
||||
longListProperty,
|
||||
doubleListProperty,
|
||||
mapProperty,
|
||||
structuredListProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Model{"
|
||||
+ "stringProperty='"
|
||||
+ stringProperty
|
||||
+ '\''
|
||||
+ ", booleanProperty='"
|
||||
+ booleanProperty
|
||||
+ '\''
|
||||
+ ", longProperty='"
|
||||
+ longProperty
|
||||
+ '\''
|
||||
+ ", doubleProperty='"
|
||||
+ doubleProperty
|
||||
+ '\''
|
||||
+ ", stringListProperty="
|
||||
+ stringListProperty
|
||||
+ ", booleanListProperty="
|
||||
+ booleanListProperty
|
||||
+ ", longListProperty="
|
||||
+ longListProperty
|
||||
+ ", doubleListProperty="
|
||||
+ doubleListProperty
|
||||
+ ", mapProperty="
|
||||
+ mapProperty
|
||||
+ ", structuredListProperty="
|
||||
+ structuredListProperty
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ListEntryModel {
|
||||
@JsonProperty("key")
|
||||
private String key;
|
||||
|
||||
@JsonProperty("value")
|
||||
private String value;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ListEntryModel that = (ListEntryModel) o;
|
||||
return Objects.equals(key, that.key) && Objects.equals(value, that.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ListEntryModel{" + "key='" + key + '\'' + ", value='" + value + '\'' + '}';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,8 +51,7 @@ public abstract class AbstractDefaultLoggerTest {
|
|||
() ->
|
||||
getLogger()
|
||||
.logRecordBuilder()
|
||||
// TODO (trask) once event name stabilizes
|
||||
// .setEventName("event name")
|
||||
.setEventName("event name")
|
||||
.setTimestamp(100, TimeUnit.SECONDS)
|
||||
.setTimestamp(Instant.now())
|
||||
.setObservedTimestamp(100, TimeUnit.SECONDS)
|
||||
|
|
|
@ -25,7 +25,7 @@ import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for No-op {@link Meter}. */
|
||||
@SuppressLogger()
|
||||
@SuppressLogger
|
||||
public abstract class AbstractDefaultMeterTest {
|
||||
private final Meter meter = getMeter();
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@ nexusPublishing {
|
|||
packageGroup.set("io.opentelemetry")
|
||||
|
||||
repositories {
|
||||
// see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/#configuration
|
||||
sonatype {
|
||||
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
|
||||
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
|
||||
username.set(System.getenv("SONATYPE_USER"))
|
||||
password.set(System.getenv("SONATYPE_KEY"))
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ plugins {
|
|||
`kotlin-dsl`
|
||||
|
||||
// When updating, update below in dependencies too
|
||||
id("com.diffplug.spotless") version "7.0.2"
|
||||
id("com.diffplug.spotless") version "7.2.1"
|
||||
}
|
||||
|
||||
if (!hasLauncherForJavaVersion(17)) {
|
||||
|
@ -50,24 +50,23 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(enforcedPlatform("com.squareup.wire:wire-bom:5.2.1"))
|
||||
implementation(enforcedPlatform("com.squareup.wire:wire-bom:5.3.5"))
|
||||
implementation("com.google.auto.value:auto-value-annotations:1.11.0")
|
||||
// When updating, update above in plugins too
|
||||
implementation("com.diffplug.spotless:spotless-plugin-gradle:7.0.2")
|
||||
// Needed for japicmp but not automatically brought in for some reason.
|
||||
implementation("com.google.guava:guava:33.4.0-jre")
|
||||
implementation("com.diffplug.spotless:spotless-plugin-gradle:7.2.1")
|
||||
implementation("com.gradle.develocity:com.gradle.develocity.gradle.plugin:4.1")
|
||||
implementation("com.squareup:javapoet:1.13.0")
|
||||
implementation("com.squareup.wire:wire-compiler")
|
||||
implementation("com.squareup.wire:wire-gradle-plugin")
|
||||
implementation("gradle.plugin.com.google.protobuf:protobuf-gradle-plugin:0.8.18")
|
||||
implementation("gradle.plugin.io.morethan.jmhreport:gradle-jmh-report:0.9.6")
|
||||
implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.5")
|
||||
implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.6")
|
||||
implementation("me.champeau.jmh:jmh-gradle-plugin:0.7.3")
|
||||
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.1.0")
|
||||
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.3.0")
|
||||
implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.2.0")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.10")
|
||||
implementation("org.owasp:dependency-check-gradle:12.0.2")
|
||||
implementation("ru.vyarus:gradle-animalsniffer-plugin:2.0.0")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.0")
|
||||
implementation("org.owasp:dependency-check-gradle:12.1.3")
|
||||
implementation("ru.vyarus:gradle-animalsniffer-plugin:2.0.1")
|
||||
}
|
||||
|
||||
// We can't apply conventions to this build so include important ones such as the Java compilation
|
||||
|
|
|
@ -50,7 +50,6 @@ tasks {
|
|||
disable("UnnecessarilyFullyQualified")
|
||||
|
||||
// We use animal sniffer
|
||||
disable("Java7ApiChecker")
|
||||
disable("Java8ApiChecker")
|
||||
disable("AndroidJdkLibsChecker")
|
||||
|
||||
|
@ -87,6 +86,10 @@ tasks {
|
|||
// cognitive load is dubious.
|
||||
disable("YodaCondition")
|
||||
|
||||
// We annotate packages with @ParametersAreNonnullByDefault from com.google.code.findbugs:jsr305.
|
||||
// @NullMarked is the equivalent from jspecify.
|
||||
disable("AddNullMarkedToPackageInfo")
|
||||
|
||||
if ((name.contains("Jmh") || name.contains("Test") || project.name.contains("testing-internal")) && !project.name.equals("custom-checks")) {
|
||||
// Allow underscore in test-type method names
|
||||
disable("MemberName")
|
||||
|
|
|
@ -5,7 +5,7 @@ plugins {
|
|||
}
|
||||
|
||||
jacoco {
|
||||
toolVersion = "0.8.12"
|
||||
toolVersion = "0.8.13"
|
||||
}
|
||||
|
||||
// https://docs.gradle.org/current/samples/sample_jvm_multi_project_with_code_coverage.html
|
||||
|
|
|
@ -142,6 +142,7 @@ if (!project.hasProperty("otel.release") && !project.name.startsWith("bom")) {
|
|||
// Temporarily suppress warnings from public generated classes from :sdk-extensions:jaeger-remote-sampler
|
||||
"io.opentelemetry.sdk.extension.trace.jaeger.proto.api_v2"
|
||||
)
|
||||
annotationExcludes.add("@kotlin.Metadata")
|
||||
val baseVersionString = if (apiBaseVersion == null) "latest" else baselineVersion
|
||||
txtOutputFile.set(
|
||||
apiNewVersion?.let { file("$rootDir/docs/apidiffs/${apiNewVersion}_vs_$baselineVersion/${base.archivesName.get()}.txt") }
|
||||
|
|
|
@ -42,7 +42,7 @@ java {
|
|||
|
||||
checkstyle {
|
||||
configDirectory.set(file("$rootDir/buildscripts/"))
|
||||
toolVersion = "10.21.2"
|
||||
toolVersion = "10.26.1"
|
||||
isIgnoreFailures = false
|
||||
configProperties["rootDir"] = rootDir
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ dependencyCheck {
|
|||
"jmhRuntimeOnly")
|
||||
failBuildOnCVSS = 7.0f // fail on high or critical CVE
|
||||
analyzers.assemblyEnabled = false // not sure why its trying to analyze .NET assemblies
|
||||
nvd.apiKey = System.getenv("NVD_API_KEY")
|
||||
}
|
||||
|
||||
val testJavaVersion = gradle.startParameter.projectProperties.get("testJavaVersion")?.let(JavaVersion::toVersion)
|
||||
|
@ -113,6 +114,14 @@ tasks {
|
|||
)
|
||||
}
|
||||
|
||||
val defaultMaxRetries = if (System.getenv().containsKey("CI")) 2 else 0
|
||||
val maxTestRetries = gradle.startParameter.projectProperties["maxTestRetries"]?.toInt() ?: defaultMaxRetries
|
||||
|
||||
develocity.testRetry {
|
||||
// You can see tests that were retried by this mechanism in the collected test reports and build scans.
|
||||
maxRetries.set(maxTestRetries);
|
||||
}
|
||||
|
||||
testLogging {
|
||||
exceptionFormat = TestExceptionFormat.FULL
|
||||
showExceptions = true
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
plugins {
|
||||
id("otel.java-conventions")
|
||||
id("otel.publish-conventions")
|
||||
|
||||
id("otel.animalsniffer-conventions")
|
||||
}
|
||||
|
||||
description = "OpenTelemetry API Common"
|
||||
otelJava.moduleName.set("io.opentelemetry.common")
|
||||
|
||||
dependencies {
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.common;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/** A loader for components that are discovered via SPI. */
|
||||
public interface ComponentLoader {
|
||||
/**
|
||||
* Load implementations of an SPI.
|
||||
*
|
||||
* @param spiClass the SPI class
|
||||
* @param <T> the SPI type
|
||||
* @return iterable of SPI implementations
|
||||
*/
|
||||
<T> Iterable<T> load(Class<T> spiClass);
|
||||
|
||||
/**
|
||||
* Create an instance for the {@code classLoader} using {@link ServiceLoader#load(Class,
|
||||
* ClassLoader)}.
|
||||
*/
|
||||
static ComponentLoader forClassLoader(ClassLoader classLoader) {
|
||||
return new ServiceLoaderComponentLoader(classLoader);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.common;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
class ServiceLoaderComponentLoader implements ComponentLoader {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
ServiceLoaderComponentLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Iterable<T> load(Class<T> spiClass) {
|
||||
return ServiceLoader.load(spiClass, classLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServiceLoaderComponentLoader{classLoader=" + classLoader + "}";
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ description = "OpenTelemetry Context (Incubator)"
|
|||
otelJava.moduleName.set("io.opentelemetry.context")
|
||||
|
||||
dependencies {
|
||||
api(project(":common"))
|
||||
// MustBeClosed
|
||||
compileOnly("com.google.errorprone:error_prone_annotations")
|
||||
|
||||
|
|
|
@ -268,6 +268,9 @@ public interface Context {
|
|||
* making this the {@linkplain Context#current() current context} before each execution.
|
||||
*/
|
||||
default ExecutorService wrap(ExecutorService executor) {
|
||||
if (executor instanceof ContextExecutorService) {
|
||||
return executor;
|
||||
}
|
||||
return new ContextExecutorService(this, executor);
|
||||
}
|
||||
|
||||
|
@ -277,6 +280,9 @@ public interface Context {
|
|||
* execution.
|
||||
*/
|
||||
default ScheduledExecutorService wrap(ScheduledExecutorService executor) {
|
||||
if (executor instanceof ContextScheduledExecutorService) {
|
||||
return executor;
|
||||
}
|
||||
return new ContextScheduledExecutorService(this, executor);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ package io.opentelemetry.context;
|
|||
* private static final ContextKey<MyState> KEY = ContextKey.named("MyState");
|
||||
*
|
||||
* public Context startWork() {
|
||||
* return Context.withValues(KEY, new MyState());
|
||||
* return Context.with(KEY, new MyState());
|
||||
* }
|
||||
*
|
||||
* public void continueWork(Context context) {
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
|
||||
package io.opentelemetry.context;
|
||||
|
||||
import io.opentelemetry.common.ComponentLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
|
@ -103,8 +103,10 @@ final class LazyStorage {
|
|||
return ContextStorage.defaultStorage();
|
||||
}
|
||||
|
||||
ComponentLoader componentLoader =
|
||||
ComponentLoader.forClassLoader(LazyStorage.class.getClassLoader());
|
||||
List<ContextStorageProvider> providers = new ArrayList<>();
|
||||
for (ContextStorageProvider provider : ServiceLoader.load(ContextStorageProvider.class)) {
|
||||
for (ContextStorageProvider provider : componentLoader.load(ContextStorageProvider.class)) {
|
||||
if (provider
|
||||
.getClass()
|
||||
.getName()
|
||||
|
@ -127,7 +129,8 @@ final class LazyStorage {
|
|||
deferredStorageFailure.set(
|
||||
new IllegalStateException(
|
||||
"Found multiple ContextStorageProvider. Set the "
|
||||
+ "io.opentelemetry.context.ContextStorageProvider property to the fully "
|
||||
+ CONTEXT_STORAGE_PROVIDER_PROPERTY
|
||||
+ " property to the fully "
|
||||
+ "qualified class name of the provider to use. Falling back to default "
|
||||
+ "ContextStorage. Found providers: "
|
||||
+ providers));
|
||||
|
@ -142,7 +145,8 @@ final class LazyStorage {
|
|||
|
||||
deferredStorageFailure.set(
|
||||
new IllegalStateException(
|
||||
"io.opentelemetry.context.ContextStorageProvider property set but no matching class "
|
||||
CONTEXT_STORAGE_PROVIDER_PROPERTY
|
||||
+ " property set but no matching class "
|
||||
+ "could be found, requested: "
|
||||
+ providerClassName
|
||||
+ " but found providers: "
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
package io.opentelemetry.context.propagation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
|
@ -33,4 +35,24 @@ public interface TextMapGetter<C> {
|
|||
*/
|
||||
@Nullable
|
||||
String get(@Nullable C carrier, String key);
|
||||
|
||||
/**
|
||||
* If implemented, returns all values for a given {@code key} in order, or returns an empty list.
|
||||
*
|
||||
* <p>The default method returns the first value of the given propagation {@code key} as a
|
||||
* singleton list, or returns an empty list.
|
||||
*
|
||||
* @param carrier carrier of propagation fields, such as an http request.
|
||||
* @param key the key of the field.
|
||||
* @return all values for a given {@code key} in order, or returns an empty list. Default method
|
||||
* wraps {@code get()} as an {@link Iterator}.
|
||||
* @since 1.50.0
|
||||
*/
|
||||
default Iterator<String> getAll(@Nullable C carrier, String key) {
|
||||
String first = get(carrier, key);
|
||||
if (first == null) {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
return Collections.singleton(first).iterator();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,39 +6,16 @@
|
|||
package io.opentelemetry.context.propagation.internal;
|
||||
|
||||
import io.opentelemetry.context.propagation.TextMapGetter;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Extends {@link TextMapGetter} to return possibly multiple values for a given key.
|
||||
* Extended {@link TextMapGetter} with experimental APIs.
|
||||
*
|
||||
* <p>This class is internal and experimental. Its APIs are unstable and can change at any time. Its
|
||||
* APIs (or a version of them) may be promoted to the public stable API in the future, but no
|
||||
* guarantees are made.
|
||||
*
|
||||
* @param <C> carrier of propagation fields, such as an http request.
|
||||
*/
|
||||
public interface ExtendedTextMapGetter<C> extends TextMapGetter<C> {
|
||||
/**
|
||||
* If implemented, returns all values for a given {@code key} in order, or returns an empty list.
|
||||
*
|
||||
* <p>The default method returns the first value of the given propagation {@code key} as a
|
||||
* singleton list, or returns an empty list.
|
||||
*
|
||||
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
|
||||
* at any time.
|
||||
*
|
||||
* @param carrier carrier of propagation fields, such as an http request.
|
||||
* @param key the key of the field.
|
||||
* @return all values for a given {@code key} in order, or returns an empty list. Default method
|
||||
* wraps {@code get()} as an {@link Iterator}.
|
||||
*/
|
||||
default Iterator<String> getAll(@Nullable C carrier, String key) {
|
||||
String first = get(carrier, key);
|
||||
if (first == null) {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
return Collections.singleton(first).iterator();
|
||||
}
|
||||
|
||||
// keep this class even if it is empty, since experimental methods may be added in the future.
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.context;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
|
@ -108,6 +109,12 @@ class ContextTest {
|
|||
assertThat(Context.current().get(ANIMAL)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void keyEqualityIsInstanceCheck() {
|
||||
Context context = Context.current().with(ContextKey.named("animal"), "cat");
|
||||
assertNull(context.get(ContextKey.named("animal"))); // yup
|
||||
}
|
||||
|
||||
@Test
|
||||
void newThreadStartsWithRoot() throws Exception {
|
||||
Context context = Context.current().with(ANIMAL, "cat");
|
||||
|
@ -361,6 +368,24 @@ class ContextTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrapExecutorService() {
|
||||
// given
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
// when
|
||||
ExecutorService firstWrap = CAT.wrap(executorService);
|
||||
ExecutorService secondWrap = CAT.wrap(firstWrap);
|
||||
|
||||
// then
|
||||
assertThat(firstWrap).isInstanceOf(ContextExecutorService.class);
|
||||
assertThat(((ContextExecutorService) firstWrap).context()).isEqualTo(CAT);
|
||||
assertThat(((ContextExecutorService) firstWrap).delegate()).isEqualTo(executorService);
|
||||
assertThat(secondWrap).isInstanceOf(ContextExecutorService.class);
|
||||
assertThat(((ContextExecutorService) secondWrap).context()).isEqualTo(CAT);
|
||||
assertThat(((ContextExecutorService) secondWrap).delegate()).isEqualTo(executorService);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class WrapExecutorService {
|
||||
|
@ -504,6 +529,25 @@ class ContextTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrapScheduledExecutorService() {
|
||||
// given
|
||||
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
// when
|
||||
ScheduledExecutorService firstWrap = CAT.wrap(executorService);
|
||||
ScheduledExecutorService secondWrap = CAT.wrap(firstWrap);
|
||||
|
||||
// then
|
||||
assertThat(firstWrap).isInstanceOf(ContextScheduledExecutorService.class);
|
||||
assertThat(((ContextScheduledExecutorService) firstWrap).context()).isEqualTo(CAT);
|
||||
assertThat(((ContextScheduledExecutorService) firstWrap).delegate()).isEqualTo(executorService);
|
||||
assertThat(secondWrap).isInstanceOf(ContextScheduledExecutorService.class);
|
||||
assertThat(((ContextScheduledExecutorService) secondWrap).context()).isEqualTo(CAT);
|
||||
assertThat(((ContextScheduledExecutorService) secondWrap).delegate())
|
||||
.isEqualTo(executorService);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class WrapScheduledExecutorService {
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.context.propagation.internal;
|
||||
package io.opentelemetry.context.propagation;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
@ -15,9 +16,9 @@ import java.util.List;
|
|||
import javax.annotation.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ExtendedTextMapGetterTest {
|
||||
class TextMapGetterTest {
|
||||
|
||||
final ExtendedTextMapGetter<Void> nullGet =
|
||||
final TextMapGetter<Void> nullGet =
|
||||
new ExtendedTextMapGetter<Void>() {
|
||||
@Override
|
||||
public Iterable<String> keys(Void carrier) {
|
||||
|
@ -31,7 +32,7 @@ class ExtendedTextMapGetterTest {
|
|||
}
|
||||
};
|
||||
|
||||
final ExtendedTextMapGetter<Void> nonNullGet =
|
||||
final TextMapGetter<Void> nonNullGet =
|
||||
new ExtendedTextMapGetter<Void>() {
|
||||
@Override
|
||||
public Iterable<String> keys(Void carrier) {
|
|
@ -3,7 +3,7 @@ plugins {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.google.errorprone:error_prone_core")
|
||||
compileOnly("com.google.errorprone:error_prone_core")
|
||||
|
||||
testImplementation("com.google.errorprone:error_prone_test_helpers")
|
||||
}
|
||||
|
@ -80,3 +80,8 @@ configurations {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip OWASP dependencyCheck task on test module
|
||||
dependencyCheck {
|
||||
skip = true
|
||||
}
|
||||
|
|
|
@ -11,14 +11,48 @@ import org.junit.jupiter.api.Test;
|
|||
class OtelInternalJavadocTest {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
doTest("internal/InternalJavadocPositiveCases.java");
|
||||
doTest("internal/InternalJavadocNegativeCases.java");
|
||||
void positiveCases() {
|
||||
CompilationTestHelper.newInstance(OtelInternalJavadoc.class, OtelInternalJavadocTest.class)
|
||||
.addSourceLines(
|
||||
"internal/InternalJavadocPositiveCases.java",
|
||||
"/*",
|
||||
" * Copyright The OpenTelemetry Authors",
|
||||
" * SPDX-License-Identifier: Apache-2.0",
|
||||
" */",
|
||||
"package io.opentelemetry.gradle.customchecks.internal;",
|
||||
"// BUG: Diagnostic contains: doesn't end with any of the applicable javadoc disclaimers",
|
||||
"public class InternalJavadocPositiveCases {",
|
||||
" // BUG: Diagnostic contains: doesn't end with any of the applicable javadoc disclaimers",
|
||||
" public static class One {}",
|
||||
" /** Doesn't have the disclaimer. */",
|
||||
" // BUG: Diagnostic contains: doesn't end with any of the applicable javadoc disclaimers",
|
||||
" public static class Two {}",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
private static void doTest(String path) {
|
||||
@Test
|
||||
void negativeCases() {
|
||||
CompilationTestHelper.newInstance(OtelInternalJavadoc.class, OtelInternalJavadocTest.class)
|
||||
.addSourceFile(path)
|
||||
.addSourceLines(
|
||||
"internal/InternalJavadocNegativeCases.java",
|
||||
"/*",
|
||||
" * Copyright The OpenTelemetry Authors",
|
||||
" * SPDX-License-Identifier: Apache-2.0",
|
||||
" */",
|
||||
"package io.opentelemetry.gradle.customchecks.internal;",
|
||||
"/**",
|
||||
" * This class is internal and is hence not for public use. Its APIs are unstable and can change at",
|
||||
" * any time.",
|
||||
" */",
|
||||
"public class InternalJavadocNegativeCases {",
|
||||
" /**",
|
||||
" * This class is internal and is hence not for public use. Its APIs are unstable and can change at",
|
||||
" * any time.",
|
||||
" */",
|
||||
" public static class One {}",
|
||||
" static class Two {}",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.gradle.customchecks.internal;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public class InternalJavadocNegativeCases {
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public static class One {}
|
||||
|
||||
static class Two {}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue