-
Notifications
You must be signed in to change notification settings - Fork 978
feat(semantic-conventions): update semantic conventions to v1.29.0 #5356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
dbbcd31
feat(semantic-conventions): update semantic conventions to v1.29.0
trentm 1f52030
markdown lint fix, add PR number
trentm 1022386
Merge branch 'main' into tm-semconv-1.29.0
trentm 3b786b1
alternative weaver config to skip attributes that accidentally don't …
trentm fddc720
style changes to semconv changelog entry
trentm 214cfd1
slight tweak to the comments on deprecated exports (include the value…
trentm f438ae3
add a note about a coming weaver improvement that we'd like to use in…
trentm d7a4760
Merge branch 'main' into tm-semconv-1.29.0
trentm 19be0f7
fix typo
trentm 7296579
typo
trentm 3463e5d
improve usage, give a working exapmle comparing two versions; break u…
trentm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| opentelemetry-specification/ | ||
| semantic-conventions/ | ||
| tmp-changelog-gen/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,309 @@ | ||
| #!/usr/bin/env node | ||
| /** | ||
| * A script to generate a meaningful changelog entry for an update in | ||
| * semantic conventions version. | ||
| * | ||
| * Usage: | ||
| * vi scripts/semconv/generate.sh # Typically update SPEC_VERSION to latest. | ||
| * ./scripts/semconv/generate.sh # Re-generate the semconv package exports. | ||
| * ./scripts/semconv/changelog-gen.sh | ||
| * | ||
| * The last command (this script) will output a text block that can be used | ||
| * in "semantic-conventions/CHANGELOG.md" (and also perhaps in the PR | ||
| * desciption). | ||
trentm marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| */ | ||
|
|
||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const globSync = require('glob').sync; | ||
| const {execSync} = require('child_process'); | ||
| const rimraf = require('rimraf'); | ||
|
|
||
| const TOP = path.resolve(__dirname, '..', '..'); | ||
| const TMP_DIR = path.join(__dirname, 'tmp-changelog-gen'); | ||
|
|
||
| /** | ||
| * Convert a string to an HTML anchor string, as Markdown does for headers. | ||
| */ | ||
| function slugify(s) { | ||
| const slug = s.trim().replace(/ /g, '-').replace(/[^\w-]/g, '') | ||
| return slug; | ||
| } | ||
|
|
||
| /** | ||
| * Given some JS `src` (typically from OTel build/esnext/... output), return | ||
| * whether the given export name `k` is marked `@deprecated`. | ||
| * | ||
| * Some of this parsing is shared with "contrib/scripts/gen-semconv-ts.js". | ||
| * | ||
| * @returns {boolean|string} `false` if not deprecated, a string deprecated | ||
| * message if deprecated and the message could be determined, otherwise | ||
| * `true` if marked deprecated. | ||
| */ | ||
| function isDeprecated(src, k) { | ||
| const re = new RegExp(`^export const ${k} = .*;$`, 'm') | ||
| const match = re.exec(src); | ||
| if (!match) { | ||
| throw new Error(`could not find the "${k}" export in semconv build/esnext/ source files`); | ||
| } | ||
|
|
||
| // Find a preceding block comment, if any. | ||
| const WHITESPACE_CHARS = [' ', '\t', '\n', '\r']; | ||
| let idx = match.index - 1; | ||
| while (idx >=1 && WHITESPACE_CHARS.includes(src[idx])) { | ||
| idx--; | ||
| } | ||
| if (src.slice(idx-1, idx+1) !== '*/') { | ||
| // There is not a block comment preceding the export. | ||
| return false; | ||
| } | ||
| idx -= 2; | ||
| while (idx >= 0) { | ||
| if (src[idx] === '/' && src[idx+1] === '*') { | ||
| // Found the start of the block comment. | ||
| const blockComment = src.slice(idx, match.index); | ||
| if (!blockComment.includes('@deprecated')) { | ||
| return false; | ||
| } | ||
| const deprecatedMsgMatch = /^\s*\*\s*@deprecated\s+(.*)$/m.exec(blockComment); | ||
| if (deprecatedMsgMatch) { | ||
| return deprecatedMsgMatch[1]; | ||
| } else { | ||
| return true; | ||
| } | ||
| } | ||
| idx--; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| function summarizeChanges({prev, curr, prevSrc, currSrc}) { | ||
| const prevNames = new Set(Object.keys(prev)); | ||
| const currNames = new Set(Object.keys(curr)); | ||
| const valChanged = (a, b) => { | ||
| if (typeof a !== typeof b) { | ||
| return true; | ||
| } else if (typeof a === 'function') { | ||
| return a.toString() !== b.toString(); | ||
| } else { | ||
| return a !== b; | ||
| } | ||
| }; | ||
| const isNewlyDeprecated = (k) => { | ||
| const isPrevDeprecated = prevNames.has(k) && isDeprecated(prevSrc, k); | ||
| const isCurrDeprecated = currNames.has(k) && isDeprecated(currSrc, k); | ||
| if (isPrevDeprecated && !isCurrDeprecated) { | ||
| throw new Error(`semconv export '${k}' was *un*-deprecated in this release!? Wassup?`); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
😄 |
||
| } | ||
| return (!isPrevDeprecated && isCurrDeprecated); | ||
| }; | ||
|
|
||
| // Determine changes. | ||
| const changes = []; | ||
| for (let k of Object.keys(curr)) { | ||
| if (!prevNames.has(k)) { | ||
| // 'ns' is the "namespace". The value here is wrong for "FEATURE_FLAG", | ||
| // "GEN_AI", etc. But good enough for the usage below. | ||
| const ns = /^(ATTR_|METRIC_|)?([^_]+)_/.exec(k)[2]; | ||
| changes.push({type: 'new', k, v: curr[k], ns}); | ||
| } else if (valChanged(curr[k], prev[k])) { | ||
| changes.push({type: 'changed', k, v: curr[k], prevV: prev[k]}); | ||
| } else { | ||
| const deprecatedResult = isNewlyDeprecated(k); | ||
| if (deprecatedResult) { | ||
| changes.push({type: 'deprecated', k, deprecatedResult}); | ||
| } | ||
| } | ||
| } | ||
| for (let k of Object.keys(prev)) { | ||
| if (!currNames.has(k)) { | ||
| changes.push({change: 'removed', k, prevV: prev[k]}); | ||
| } | ||
| } | ||
|
|
||
| // Create a summary of changes, grouped by change type. | ||
| const summary = []; | ||
| const execSummary = []; | ||
|
|
||
| const added = changes.filter(ch => ch.type === 'new'); | ||
| if (added.length) { | ||
| execSummary.push(`${added.length} added`); | ||
| summary.push(`// Added (${added.length})`); | ||
| let last, lastAttr; | ||
| const longest = added.reduce((acc, ch) => Math.max(acc, ch.k.length), 0); | ||
| added.forEach(ch => { | ||
| if (last && ch.ns !== last.ns) { summary.push(''); } | ||
| let indent = ''; | ||
| if (lastAttr && ch.k.startsWith(lastAttr.k.slice('ATTR_'.length))) { | ||
| indent = ' '; | ||
| } | ||
| const cindent = ' '.repeat(longest - ch.k.length + 1); | ||
|
|
||
| const vRepr = ch.k.includes('_VALUE_') ? JSON.stringify(ch.v) : ch.v | ||
| summary.push(`${indent}${ch.k}${cindent}// ${vRepr}`); | ||
|
|
||
| last = ch; | ||
| if (ch.k.startsWith('ATTR_')) { | ||
| lastAttr = ch; | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| const changed = changes.filter(ch => ch.type === 'changed'); | ||
| if (changed.length) { | ||
| execSummary.push(`${changed.length} changed value`); | ||
| if (summary.length) { summary.push(''); } | ||
| summary.push(`// Changed (${changed.length})`); | ||
| let last; | ||
| const longest = changed.reduce((acc, ch) => Math.max(acc, ch.k.length), 0); | ||
| changed.forEach(ch => { | ||
| if (last && ch.ns !== last.ns) { summary.push(''); } | ||
| const cindent = ' '.repeat(longest - ch.k.length + 1); | ||
|
|
||
| const prevVRepr = ch.prevV.includes('_VALUE_') ? JSON.stringify(ch.prevV) : ch.prevV; | ||
| const vRepr = ch.k.includes('_VALUE_') ? JSON.stringify(ch.v) : ch.v; | ||
| summary.push(`${ch.k}${cindent}// ${prevVRepr} -> ${vRepr}`); | ||
|
|
||
| last = ch; | ||
| }); | ||
| } | ||
|
|
||
| const deprecated = changes.filter(ch => ch.type === 'deprecated'); | ||
| if (deprecated.length) { | ||
| execSummary.push(`${deprecated.length} newly deprecated`); | ||
| if (summary.length) { summary.push(''); } | ||
| summary.push(`// Deprecated (${deprecated.length})`); | ||
| let last; | ||
| const longest = deprecated.reduce((acc, ch) => Math.max(acc, ch.k.length), 0); | ||
| deprecated.forEach(ch => { | ||
| if (last && ch.ns !== last.ns) { summary.push(''); } | ||
| const cindent = ' '.repeat(longest - ch.k.length + 1); | ||
|
|
||
| if (typeof ch.deprecatedResult === 'string') { | ||
| summary.push(`${ch.k}${cindent}// ${ch.deprecatedResult}`); | ||
| } else { | ||
| summary.push(ch.k) | ||
| } | ||
|
|
||
| last = ch; | ||
| }); | ||
| } | ||
|
|
||
| const removed = changes.filter(ch => ch.type === 'removed'); | ||
| if (removed.length) { | ||
| execSummary.push(`${removed.length} removed`); | ||
| if (summary.length) { summary.push(''); } | ||
| summary.push(`// Removed (${removed.length})`); | ||
| let last; | ||
| const longest = removed.reduce((acc, ch) => Math.max(acc, ch.k.length), 0); | ||
| removed.forEach(ch => { | ||
| if (last && ch.ns !== last.ns) { summary.push(''); } | ||
| const cindent = ' '.repeat(longest - ch.k.length + 1); | ||
|
|
||
| const prevVRepr = ch.prevV.includes('_VALUE_') ? JSON.stringify(ch.prevV) : ch.prevV; | ||
| summary.push(`${ch.k}${cindent}// ${prevVRepr}`); | ||
|
|
||
| last = ch; | ||
| }); | ||
| } | ||
| if (execSummary.length === 0) { | ||
| execSummary.push('*none*'); | ||
| } | ||
|
|
||
| return [execSummary, summary]; | ||
| } | ||
|
|
||
|
|
||
| function semconvChangelogGen() { | ||
| // Determine target spec ver. | ||
| const generateShPath = path.join(__dirname, 'generate.sh'); | ||
| const specVerRe = /^SPEC_VERSION=(.*)$/m; | ||
| const specVerMatch = specVerRe.exec(fs.readFileSync(generateShPath)); | ||
| if (!specVerMatch) { | ||
| throw new Error(`could not determine current semconv SPEC_VERSION: ${specVerRe} did not match in ${generateShPath}`); | ||
| } | ||
| const specVer = specVerMatch[1].trim(); | ||
| console.log('Target Semantic Conventions ver is:', specVer); | ||
|
|
||
| console.log(`Creating tmp working dir "${TMP_DIR}"`); | ||
| rimraf.sync(TMP_DIR); | ||
| fs.mkdirSync(TMP_DIR); | ||
|
|
||
| const scDir = path.join(TOP, 'semantic-conventions'); | ||
| const pj = JSON.parse(fs.readFileSync(path.join(scDir, 'package.json'))); | ||
| const pkgInfo = JSON.parse(execSync(`npm info -j ${pj.name}`)) | ||
| console.log(`Previous published version for comparison is: ${pkgInfo.version}`); | ||
|
|
||
| console.log(`Downloading and extracting @opentelemetry/semantic-conventions@${pkgInfo.version}`) | ||
| execSync(`curl -sf -o - ${pkgInfo.dist.tarball} | tar xzf -`, { cwd: TMP_DIR }); | ||
|
|
||
| console.log(`Comparing exports to "${scDir}"`) | ||
| const [stableExecSummary, stableSummary] = summarizeChanges({ | ||
| // require('.../build/src/stable_*.js') from previous and current. | ||
| prev: Object.assign(...globSync(path.join(TMP_DIR, 'package/build/src/stable_*.js')).map(require)), | ||
| curr: Object.assign(...globSync(path.join(scDir, 'build/src/stable_*.js')).map(require)), | ||
| // Load '.../build/esnext/stable_*.js' sources to use for parsing jsdoc comments. | ||
| prevSrc: globSync(path.join(TMP_DIR, 'package/build/esnext/stable_*.js')) | ||
| .map(f => fs.readFileSync(f, 'utf8')) | ||
| .join('\n\n'), | ||
| currSrc: globSync(path.join(scDir, 'build/esnext/stable_*.js')) | ||
| .map(f => fs.readFileSync(f, 'utf8')) | ||
| .join('\n\n'), | ||
| }); | ||
| const [unstableExecSummary, unstableSummary] = summarizeChanges({ | ||
| prev: Object.assign(...globSync(path.join(TMP_DIR, 'package/build/src/experimental_*.js')).map(require)), | ||
| curr: Object.assign(...globSync(path.join(scDir, 'build/src/experimental_*.js')).map(require)), | ||
| prevSrc: globSync(path.join(TMP_DIR, 'package/build/esnext/experimental_*.js')) | ||
| .map(f => fs.readFileSync(f, 'utf8')) | ||
| .join('\n\n'), | ||
| currSrc: globSync(path.join(scDir, 'build/esnext/experimental_*.js')) | ||
| .map(f => fs.readFileSync(f, 'utf8')) | ||
| .join('\n\n'), | ||
| }); | ||
|
|
||
| const changelogEntry = [` | ||
| * feat: update semantic conventions to ${specVer} [#NNNN] | ||
| * Semantic Conventions ${specVer}: | ||
| [changelog](https://github.com/open-telemetry/semantic-conventions/blob/main/CHANGELOG.md#${slugify(specVer)}) | | ||
| [latest docs](https://opentelemetry.io/docs/specs/semconv/) | ||
| * \`@opentelemetry/semantic-conventions\` (stable) export changes: ${stableExecSummary.join(', ')} | ||
| * \`@opentelemetry/semantic-conventions/incubating\` (unstable) export changes: ${unstableExecSummary.join(', ')} | ||
| `]; | ||
|
|
||
| if (stableSummary.length) { | ||
| changelogEntry.push(''); | ||
| changelogEntry.push(`##### Stable changes ${specVer}\n`); | ||
| changelogEntry.push('```js'); | ||
| changelogEntry.push(stableSummary.join('\n')); | ||
| changelogEntry.push('```'); | ||
| } | ||
|
|
||
| if (unstableSummary.length) { | ||
| if (stableSummary.length) { | ||
| changelogEntry.push(''); | ||
| } | ||
| changelogEntry.push(`#### Unstable changes ${specVer}`); | ||
| changelogEntry.push(` | ||
| <details> | ||
| <summary>Full unstable changes</summary> | ||
| \`\`\`js | ||
| ${unstableSummary.join('\n')} | ||
| \`\`\` | ||
| </details> | ||
| `); | ||
| } | ||
|
|
||
| return changelogEntry.join('\n'); | ||
| } | ||
|
|
||
| function main() { | ||
| const s = semconvChangelogGen(); | ||
| console.log('The following could be added to the top "Enhancement" section of "semantic-conventions/CHANGELOG.md":'); | ||
| console.log('\n- - -'); | ||
| console.log(s) | ||
| console.log('- - -'); | ||
| } | ||
|
|
||
| main(); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,11 +7,11 @@ ROOT_DIR="${SCRIPT_DIR}/../../" | |
|
|
||
| # Get latest version by running `git tag -l --sort=version:refname | tail -1` | ||
| # ... in [email protected]:open-telemetry/semantic-conventions.git | ||
| SPEC_VERSION=v1.28.0 | ||
| SPEC_VERSION=v1.29.0 | ||
| # ... in [email protected]:open-telemetry/weaver.git | ||
| GENERATOR_VERSION=v0.10.0 | ||
|
|
||
| # When running on windows and your are getting references to ";C" (like Telemetry;C) | ||
| # When running on windows and you are getting references to ";C" (like Telemetry;C) | ||
| # then this is an issue with the bash shell, so first run the following in your shell: | ||
| # export MSYS_NO_PATHCONV=1 | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.