Skip to content

Commit

Permalink
feat: add new keys to element and dependency metrics (#169)
Browse files Browse the repository at this point in the history
* feat: add new keys to element and dependency metrics

* fix: pull in npm and jsx attributes from @ibm/telemetry-attributes-js
  • Loading branch information
francinelucca committed Jan 18, 2024
1 parent 128bde5 commit 10ddf21
Show file tree
Hide file tree
Showing 12 changed files with 363 additions and 224 deletions.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"devDependencies": {
"@commitlint/cli": "^17.8.1",
"@commitlint/config-conventional": "^17.8.1",
"@ibm/telemetry-attributes-js": "^2.0.0",
"@ibm/telemetry-config-schema": "^0.3.0",
"@opentelemetry/api": "^1.7.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.46.0",
Expand Down
22 changes: 0 additions & 22 deletions src/main/scopes/jsx/jsx-scope-attributes.ts

This file was deleted.

23 changes: 17 additions & 6 deletions src/main/scopes/jsx/jsx-scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Scope } from '../../core/scope.js'
import { EmptyScopeError } from '../../exceptions/empty-scope.error.js'
import { getDirectoryPrefix } from '../npm/get-directory-prefix.js'
import { getPackageData } from '../npm/get-package-data.js'
import { PackageData } from '../npm/interfaces.js'
import { AllImportMatcher } from './import-matchers/all-import-matcher.js'
import { NamedImportMatcher } from './import-matchers/named-import-matcher.js'
import { RenamedImportMatcher } from './import-matchers/renamed-import-matcher.js'
Expand Down Expand Up @@ -71,9 +72,9 @@ export class JsxScope extends Scope {

for (const sourceFile of sourceFiles) {
if (this.runSync) {
await this.captureFileMetrics(sourceFile, instrumentedPackage.name, importMatchers)
await this.captureFileMetrics(sourceFile, instrumentedPackage, importMatchers)
} else {
promises.push(this.captureFileMetrics(sourceFile, instrumentedPackage.name, importMatchers))
promises.push(this.captureFileMetrics(sourceFile, instrumentedPackage, importMatchers))
}
}

Expand All @@ -85,18 +86,19 @@ export class JsxScope extends Scope {
* in the supplied SourceFile node.
*
* @param sourceFile - The sourcefile node to generate metrics for.
* @param instrumentedPackageName - Name of the instrumented package to capture metrics for.
* @param instrumentedPackage - Name and version of the instrumented package
* to capture metrics for.
* @param importMatchers - Matchers instances to use for import-element matching.
*/
async captureFileMetrics(
sourceFile: ts.SourceFile,
instrumentedPackageName: string,
instrumentedPackage: PackageData,
importMatchers: JsxElementImportMatcher[]
) {
const accumulator = new JsxElementAccumulator()

this.processFile(accumulator, sourceFile)
this.removeIrrelevantImports(accumulator, instrumentedPackageName)
this.removeIrrelevantImports(accumulator, instrumentedPackage.name)
this.resolveElementImports(accumulator, importMatchers)
await this.resolveInvokers(accumulator, sourceFile.fileName)

Expand All @@ -108,7 +110,16 @@ export class JsxScope extends Scope {
return
}

this.capture(new ElementMetric(jsxElement, jsxImport, invoker, this.config, this.logger))
this.capture(
new ElementMetric(
jsxElement,
jsxImport,
invoker,
instrumentedPackage,
this.config,
this.logger
)
)
})
}

Expand Down
38 changes: 35 additions & 3 deletions src/main/scopes/jsx/metrics/element-metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { JsxScopeAttributes, NpmScopeAttributes } from '@ibm/telemetry-attributes-js'
import { type ConfigSchema } from '@ibm/telemetry-config-schema'
import { Attributes } from '@opentelemetry/api'

Expand All @@ -13,8 +14,8 @@ import { deNull } from '../../../core/de-null.js'
import { type Logger } from '../../../core/log/logger.js'
import { PackageDetailsProvider } from '../../../core/package-details-provider.js'
import { ScopeMetric } from '../../../core/scope-metric.js'
import { PackageData } from '../../npm/interfaces.js'
import { type JsxElement, type JsxElementAttribute, type JsxImport } from '../interfaces.js'
import { JsxScopeAttributes } from '../jsx-scope-attributes.js'

/**
* JSX scope metric that generates a jsx.element individual metric for a given element.
Expand All @@ -26,27 +27,31 @@ export class ElementMetric extends ScopeMetric {
private readonly invoker: string | undefined
private readonly allowedAttributeNames: string[]
private readonly allowedAttributeStringValues: string[]
private readonly instrumentedPackage: PackageData

/**
* Constructs a JsxElementMetric.
*
* @param jsxElement - Object containing name and version to extract data to generate metric from.
* @param matchingImport - Import that matched the provided JsxElement in the file.
* @param invoker - Name of the package that invoked the JsxElement.
* @param instrumentedPackage - Data (name and version) pertaining to instrumented package.
* @param config - Determines which attributes name and values to collect for.
* @param logger - Logger instance.
*/
public constructor(
jsxElement: JsxElement,
matchingImport: JsxImport,
invoker: string | undefined,
instrumentedPackage: PackageData,
config: ConfigSchema,
logger: Logger
) {
super(logger)
this.jsxElement = jsxElement
this.matchingImport = matchingImport
this.invoker = invoker
this.instrumentedPackage = instrumentedPackage

this.allowedAttributeNames = config.collect.jsx?.elements?.allowedAttributeNames ?? []
this.allowedAttributeStringValues =
Expand Down Expand Up @@ -82,6 +87,20 @@ export class ElementMetric extends ScopeMetric {
this.allowedAttributeStringValues
)

const packageDetailsProvider = new PackageDetailsProvider(this.logger)

const {
owner: instrumentedOwner,
name: instrumentedName,
major: instrumentedMajor,
minor: instrumentedMinor,
patch: instrumentedPatch,
preRelease: instrumentedPreRelease
} = packageDetailsProvider.getPackageDetails(
this.instrumentedPackage.name,
this.instrumentedPackage.version
)

let metricData: Attributes = {
[JsxScopeAttributes.NAME]: this.jsxElement.name,
[JsxScopeAttributes.MODULE_SPECIFIER]: this.matchingImport.path,
Expand All @@ -91,7 +110,15 @@ export class ElementMetric extends ScopeMetric {
),
[JsxScopeAttributes.INVOKER_PACKAGE_RAW]: this.invoker,
[JsxScopeAttributes.INVOKER_PACKAGE_OWNER]: invokingPackageDetails?.owner,
[JsxScopeAttributes.INVOKER_PACKAGE_NAME]: invokingPackageDetails?.name
[JsxScopeAttributes.INVOKER_PACKAGE_NAME]: invokingPackageDetails?.name,
[NpmScopeAttributes.INSTRUMENTED_RAW]: this.instrumentedPackage.name,
[NpmScopeAttributes.INSTRUMENTED_OWNER]: instrumentedOwner,
[NpmScopeAttributes.INSTRUMENTED_NAME]: instrumentedName,
[NpmScopeAttributes.INSTRUMENTED_VERSION_RAW]: this.instrumentedPackage.version,
[NpmScopeAttributes.INSTRUMENTED_VERSION_MAJOR]: instrumentedMajor?.toString(),
[NpmScopeAttributes.INSTRUMENTED_VERSION_MINOR]: instrumentedMinor?.toString(),
[NpmScopeAttributes.INSTRUMENTED_VERSION_PATCH]: instrumentedPatch?.toString(),
[NpmScopeAttributes.INSTRUMENTED_VERSION_PRE_RELEASE]: instrumentedPreRelease?.join('.')
}

// Handle renamed elements
Expand All @@ -105,7 +132,12 @@ export class ElementMetric extends ScopeMetric {
metricData = hash(metricData, [
JsxScopeAttributes.INVOKER_PACKAGE_RAW,
JsxScopeAttributes.INVOKER_PACKAGE_OWNER,
JsxScopeAttributes.INVOKER_PACKAGE_NAME
JsxScopeAttributes.INVOKER_PACKAGE_NAME,
NpmScopeAttributes.INSTRUMENTED_RAW,
NpmScopeAttributes.INSTRUMENTED_OWNER,
NpmScopeAttributes.INSTRUMENTED_NAME,
NpmScopeAttributes.INSTRUMENTED_VERSION_RAW,
NpmScopeAttributes.INSTRUMENTED_VERSION_PRE_RELEASE
])

return metricData
Expand Down
54 changes: 28 additions & 26 deletions src/main/scopes/npm/metrics/dependency-metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { NpmScopeAttributes } from '@ibm/telemetry-attributes-js'
import { Attributes } from '@opentelemetry/api'

import { hash } from '../../../core/anonymize/hash.js'
import { type Logger } from '../../../core/log/logger.js'
import { PackageDetailsProvider } from '../../../core/package-details-provider.js'
import { ScopeMetric } from '../../../core/scope-metric.js'
import { NpmScopeAttributes } from '../npm-scope-attributes.js'
import { PackageData } from '../interfaces.js'

export interface DependencyData {
rawName: string
rawVersion: string
installerRawName: string
installerRawVersion: string
isInstrumented: 'true' | 'false'
}

Expand All @@ -27,16 +26,19 @@ export class DependencyMetric extends ScopeMetric {
public override name = 'npm.dependency' as const

private readonly data: DependencyData
private readonly instrumentedPackage: PackageData

/**
* Constructs a DependencyMetric.
*
* @param data - Object containing name and version to extract data to generate metric from.
* @param instrumentedPackage - Data (name and version) pertaining to instrumented package.
* @param logger - The logger instance to use.
*/
public constructor(data: DependencyData, logger: Logger) {
public constructor(data: DependencyData, instrumentedPackage: PackageData, logger: Logger) {
super(logger)
this.data = data
this.instrumentedPackage = instrumentedPackage
}

/**
Expand All @@ -51,35 +53,35 @@ export class DependencyMetric extends ScopeMetric {
packageDetailsProvider.getPackageDetails(this.data.rawName, this.data.rawVersion)

const {
owner: installerOwner,
name: installerName,
major: installerMajor,
minor: installerMinor,
patch: installerPatch,
preRelease: installerPreRelease
owner: instrumentedOwner,
name: instrumentedName,
major: instrumentedMajor,
minor: instrumentedMinor,
patch: instrumentedPatch,
preRelease: instrumentedPreRelease
} = packageDetailsProvider.getPackageDetails(
this.data.installerRawName,
this.data.installerRawVersion
this.instrumentedPackage.name,
this.instrumentedPackage.version
)

const metricData: Attributes = {
[NpmScopeAttributes.RAW]: this.data.rawName,
[NpmScopeAttributes.OWNER]: owner,
[NpmScopeAttributes.NAME]: name,
[NpmScopeAttributes.INSTRUMENTED]: this.data.isInstrumented,
[NpmScopeAttributes.IS_INSTRUMENTED]: this.data.isInstrumented,
[NpmScopeAttributes.VERSION_RAW]: this.data.rawVersion,
[NpmScopeAttributes.VERSION_MAJOR]: major?.toString(),
[NpmScopeAttributes.VERSION_MINOR]: minor?.toString(),
[NpmScopeAttributes.VERSION_PATCH]: patch?.toString(),
[NpmScopeAttributes.VERSION_PRE_RELEASE]: preRelease?.join('.'),
[NpmScopeAttributes.INSTALLER_RAW]: this.data.installerRawName,
[NpmScopeAttributes.INSTALLER_OWNER]: installerOwner,
[NpmScopeAttributes.INSTALLER_NAME]: installerName,
[NpmScopeAttributes.INSTALLER_VERSION_RAW]: this.data.installerRawVersion,
[NpmScopeAttributes.INSTALLER_VERSION_MAJOR]: installerMajor?.toString(),
[NpmScopeAttributes.INSTALLER_VERSION_MINOR]: installerMinor?.toString(),
[NpmScopeAttributes.INSTALLER_VERSION_PATCH]: installerPatch?.toString(),
[NpmScopeAttributes.INSTALLER_VERSION_PRE_RELEASE]: installerPreRelease?.join('.')
[NpmScopeAttributes.INSTRUMENTED_RAW]: this.instrumentedPackage.name,
[NpmScopeAttributes.INSTRUMENTED_OWNER]: instrumentedOwner,
[NpmScopeAttributes.INSTRUMENTED_NAME]: instrumentedName,
[NpmScopeAttributes.INSTRUMENTED_VERSION_RAW]: this.instrumentedPackage.version,
[NpmScopeAttributes.INSTRUMENTED_VERSION_MAJOR]: instrumentedMajor?.toString(),
[NpmScopeAttributes.INSTRUMENTED_VERSION_MINOR]: instrumentedMinor?.toString(),
[NpmScopeAttributes.INSTRUMENTED_VERSION_PATCH]: instrumentedPatch?.toString(),
[NpmScopeAttributes.INSTRUMENTED_VERSION_PRE_RELEASE]: instrumentedPreRelease?.join('.')
}

return hash(metricData, [
Expand All @@ -88,11 +90,11 @@ export class DependencyMetric extends ScopeMetric {
NpmScopeAttributes.NAME,
NpmScopeAttributes.VERSION_RAW,
NpmScopeAttributes.VERSION_PRE_RELEASE,
NpmScopeAttributes.INSTALLER_RAW,
NpmScopeAttributes.INSTALLER_OWNER,
NpmScopeAttributes.INSTALLER_NAME,
NpmScopeAttributes.INSTALLER_VERSION_RAW,
NpmScopeAttributes.INSTALLER_VERSION_PRE_RELEASE
NpmScopeAttributes.INSTRUMENTED_RAW,
NpmScopeAttributes.INSTRUMENTED_OWNER,
NpmScopeAttributes.INSTRUMENTED_NAME,
NpmScopeAttributes.INSTRUMENTED_VERSION_RAW,
NpmScopeAttributes.INSTRUMENTED_VERSION_PRE_RELEASE
])
}
}
36 changes: 0 additions & 36 deletions src/main/scopes/npm/npm-scope-attributes.ts

This file was deleted.

16 changes: 6 additions & 10 deletions src/main/scopes/npm/npm-scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,10 @@ export class NpmScope extends Scope {
*/
@Trace()
private async collectDependencies(): Promise<void> {
const { name: instrumentedPkgName, version: instrumentedPkgVersion } = await getPackageData(
this.cwd,
this.logger
)
const instrumentedPkg = await getPackageData(this.cwd, this.logger)
const installingPackages = await this.findInstallingPackages(
instrumentedPkgName,
instrumentedPkgVersion
instrumentedPkg.name,
instrumentedPkg.version
)

installingPackages.forEach((installingPkg) => {
Expand All @@ -44,14 +41,13 @@ export class NpmScope extends Scope {
{
rawName: dependency.name,
rawVersion: dependency.version,
installerRawName: installingPkg.name,
installerRawVersion: installingPkg.version,
isInstrumented:
dependency.name === instrumentedPkgName &&
dependency.version === instrumentedPkgVersion
dependency.name === instrumentedPkg.name &&
dependency.version === instrumentedPkg.version
? 'true'
: 'false'
},
instrumentedPkg,
this.logger
)
)
Expand Down
Loading

0 comments on commit 10ddf21

Please sign in to comment.