Skip to content

Commit

Permalink
Merge pull request #563 from solarwinds/NH-98985
Browse files Browse the repository at this point in the history
Basic browser support
  • Loading branch information
raphael-theriault-swi authored Feb 14, 2025
2 parents 4747125 + f95801b commit e9f17be
Show file tree
Hide file tree
Showing 39 changed files with 2,177 additions and 1,181 deletions.
8 changes: 8 additions & 0 deletions .yarn/versions/177208c1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
releases:
"@solarwinds-apm/instrumentations": minor
"@solarwinds-apm/module": major
solarwinds-apm: minor

declined:
- "@solarwinds-apm/dependencies"
- "@solarwinds-apm/sampling"
11 changes: 9 additions & 2 deletions packages/instrumentations/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"exports": {
".": {
"import": "./dist/index.js"
},
"./web": {
"import": "./dist/web/index.js"
}
},
"files": [
Expand All @@ -36,6 +39,7 @@
"test": "swtest -p test/tsconfig.json -c src"
},
"dependencies": {
"@opentelemetry/auto-instrumentations-web": "^0.45.0",
"@opentelemetry/core": "~1.30.0",
"@opentelemetry/instrumentation": "~0.57.0",
"@opentelemetry/instrumentation-amqplib": "^0.46.0",
Expand Down Expand Up @@ -81,11 +85,13 @@
"@opentelemetry/resource-detector-azure": "^0.5.0",
"@opentelemetry/resource-detector-container": "^0.5.0",
"@opentelemetry/resources": "~1.30.0",
"@opentelemetry/semantic-conventions": "~1.28.0",
"@opentelemetry/winston-transport": "^0.10.0",
"@solarwinds-apm/module": "workspace:^"
},
"peerDependencies": {
"@opentelemetry/api": "^1.9.0"
"@opentelemetry/api": "^1.9.0",
"zone.js": "^0.13.0 || ^0.14.0 || ^0.15.0"
},
"peerDependenciesMeta": {
"@opentelemetry/api": {
Expand All @@ -100,7 +106,8 @@
"eslint": "^9.12.0",
"prettier": "^3.3.3",
"semver": "^7.6.3",
"typescript": "~5.7.2"
"typescript": "~5.7.2",
"zone.js": "^0.15.0"
},
"engines": {
"node": "^18.19.0 || ^20.8.0 || >=22.0.0"
Expand Down
35 changes: 35 additions & 0 deletions packages/instrumentations/src/web/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright 2023-2025 SolarWinds Worldwide, LLC.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import {
browserDetectorSync,
detectResourcesSync,
envDetectorSync,
type Resource,
} from "@opentelemetry/resources"

import { sessionIdDetector } from "./resource-detector-session-id.js"

export {
getWebAutoInstrumentations as getInstrumentations,
type InstrumentationConfigMap,
} from "@opentelemetry/auto-instrumentations-web"

export function getResource(): Resource {
return detectResourcesSync({
detectors: [browserDetectorSync, envDetectorSync, sessionIdDetector],
})
}
39 changes: 39 additions & 0 deletions packages/instrumentations/src/web/resource-detector-session-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright 2023-2025 SolarWinds Worldwide, LLC.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import { type Attributes } from "@opentelemetry/api"
import { type DetectorSync, Resource } from "@opentelemetry/resources"
import {
ATTR_SERVICE_INSTANCE_ID,
ATTR_SESSION_ID,
} from "@opentelemetry/semantic-conventions/incubating"

export const sessionIdDetector: DetectorSync = {
detect: () => {
const attributes: Attributes = {}
const id =
self.sessionStorage.getItem(ATTR_SESSION_ID) ??
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
self.crypto?.randomUUID()

if (id) {
self.sessionStorage.setItem(ATTR_SESSION_ID, id)
attributes[ATTR_SESSION_ID] = id
attributes[ATTR_SERVICE_INSTANCE_ID] = id
}
return new Resource(attributes)
},
}
6 changes: 0 additions & 6 deletions packages/module/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { env } from "node:process"

/**
* Unrefs a Node.js reference counted object so it
* doesn't prevent the runtime from shutting down
Expand All @@ -40,7 +38,3 @@ export async function load(url: string): Promise<unknown> {
if (useDefaultExport) return imported.default
else return imported
}

export const IS_AWS_LAMBDA = "AWS_LAMBDA_FUNCTION_NAME" in env

export const IS_SERVERLESS = IS_AWS_LAMBDA
32 changes: 32 additions & 0 deletions packages/solarwinds-apm/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.

import fs from "node:fs/promises"

import { agents } from "caniuse-lite"
import esbuild from "esbuild"
import eslint from "eslint"
import prettier from "prettier"

Expand All @@ -33,3 +35,33 @@ await fs.writeFile("src/version.ts", linted[0].output)

await fs.mkdir("dist/commonjs", { recursive: true })
await fs.cp("src/commonjs/package.json", "dist/commonjs/package.json")

// Generate the web instrumentation bundle to target the Chrome/Safari/Firefox/Edge
// versions which were the latest 1 year ago as a default
// People can still bundle themselves if this isn't satisfactory
const targets = Object.entries(agents)
.filter(([name]) => ["chrome", "safari", "firefox", "edge"].includes(name))
.map(([name, data]) => {
const deadline = new Date()
deadline.setFullYear(deadline.getFullYear() - 1)

const version = data.versions.findLast(
(version) =>
Number.isSafeInteger(data.release_date[version]) &&
new Date(data.release_date[version] * 1000) <= deadline,
)

return name + version
})

await esbuild.build({
entryPoints: ["src/web/index.ts"],
outfile: "dist/web.js",
format: "esm",
target: targets,
bundle: true,
minify: true,
keepNames: true,
sourcemap: "linked",
external: ["node:*"],
})
4 changes: 4 additions & 0 deletions packages/solarwinds-apm/lib.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ interface ObjectConstructor {
entries<const T extends Record<string, unknown>>(
object: T,
): { [K in keyof T]: [K, T[K]] }[keyof T][]

fromEntries<const T extends readonly [PropertyKey, unknown]>(
entries: Iterable<T>,
): Record<T[0], T[1]>
}
16 changes: 13 additions & 3 deletions packages/solarwinds-apm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
".": {
"import": "./dist/index.js",
"require": "./dist/commonjs/index.js"
},
"./web": {
"import": "./dist/web/index.js"
},
"./web.js": {
"import": "./dist/web.js"
}
},
"main": "./dist/commonjs/index.js",
Expand All @@ -57,16 +63,18 @@
},
"dependencies": {
"@opentelemetry/api-logs": "~0.57.0",
"@opentelemetry/context-zone": "~1.30.0",
"@opentelemetry/core": "~1.30.0",
"@opentelemetry/exporter-logs-otlp-proto": "~0.57.0",
"@opentelemetry/exporter-metrics-otlp-proto": "~0.57.0",
"@opentelemetry/exporter-logs-otlp-http": "~0.57.0",
"@opentelemetry/exporter-metrics-otlp-http": "~0.57.0",
"@opentelemetry/exporter-trace-otlp-proto": "~0.57.0",
"@opentelemetry/instrumentation": "~0.57.0",
"@opentelemetry/resources": "~1.30.0",
"@opentelemetry/sdk-logs": "~0.57.0",
"@opentelemetry/sdk-metrics": "~1.30.0",
"@opentelemetry/sdk-trace-base": "~1.30.0",
"@opentelemetry/sdk-trace-node": "~1.30.0",
"@opentelemetry/sdk-trace-web": "~1.30.0",
"@opentelemetry/semantic-conventions": "~1.28.0",
"@solarwinds-apm/bindings": "workspace:^",
"@solarwinds-apm/dependencies": "workspace:^",
Expand All @@ -77,7 +85,7 @@
"json-stringify-safe": "^5.0.1",
"node-releases": "^2.0.18",
"semver": "^7.6.3",
"zod": "^3.23.8"
"valibot": "1.0.0-rc.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.9.0"
Expand All @@ -93,6 +101,8 @@
"@solarwinds-apm/test": "workspace:^",
"@types/json-stringify-safe": "^5.0.3",
"@types/node": "^18.19.0",
"caniuse-lite": "^1.0",
"esbuild": "^0.24.2",
"eslint": "^9.12.0",
"prettier": "^3.3.3",
"typescript": "~5.7.2"
Expand Down
2 changes: 1 addition & 1 deletion packages/solarwinds-apm/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { SAMPLER } from "./init.js"
import { SAMPLER } from "./shared/init.js"

/**
* Wait until the library is ready to sample traces
Expand Down
2 changes: 1 addition & 1 deletion packages/solarwinds-apm/src/appoptics/exporters/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
type Histogram,
} from "@solarwinds-apm/histogram"

import { componentLogger } from "../../logger.js"
import { componentLogger } from "../../shared/logger.js"

const MAX_TAGS = 50

Expand Down
2 changes: 1 addition & 1 deletion packages/solarwinds-apm/src/appoptics/exporters/traces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ import {
} from "@opentelemetry/semantic-conventions"
import { oboe } from "@solarwinds-apm/bindings"

import { componentLogger } from "../../logger.js"
import { TRANSACTION_NAME_ATTRIBUTE } from "../../processing/transaction-name.js"
import { traceParent } from "../../propagation/headers.js"
import { componentLogger } from "../../shared/logger.js"

export class AppopticsTraceExporter implements SpanExporter {
readonly #logger = componentLogger(AppopticsTraceExporter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ import {
import { oboe } from "@solarwinds-apm/bindings"

import { type Configuration } from "../../config.js"
import { componentLogger } from "../../logger.js"
import { isRootOrEntry } from "../../processing/parent-span.js"
import {
computedTransactionName,
TRANSACTION_NAME_ATTRIBUTE,
} from "../../processing/transaction-name.js"
import { httpSpanMetadata } from "../../sampling/sampler.js"
import { componentLogger } from "../../shared/logger.js"

export class AppopticsInboundMetricsProcessor
extends NoopSpanProcessor
implements SpanProcessor
{
readonly #logger = componentLogger(AppopticsInboundMetricsProcessor)
readonly #defaultTransactionName?: string
readonly #defaultTransactionName?: () => string

constructor(config: Configuration) {
super()
Expand All @@ -57,7 +57,7 @@ export class AppopticsInboundMetricsProcessor
this.#logger.debug("initial transaction name", transaction)
if (typeof transaction !== "string") {
transaction =
this.#defaultTransactionName ?? computedTransactionName(span)
this.#defaultTransactionName?.() ?? computedTransactionName(span)
}

if (meta.http) {
Expand Down
4 changes: 2 additions & 2 deletions packages/solarwinds-apm/src/appoptics/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import {
import { oboe } from "@solarwinds-apm/bindings"

import { type Configuration } from "../config.js"
import { componentLogger } from "../logger.js"
import { modules, VERSIONS } from "../metadata.js"
import { componentLogger } from "../shared/logger.js"
import { VERSION } from "../version.js"
import certificate from "./certificate.js"

Expand All @@ -41,7 +41,7 @@ export async function reporter(
resource: Resource,
): Promise<oboe.Reporter> {
const reporter = new oboe.Reporter({
service_key: `${config.serviceKey?.token}:${config.service}`,
service_key: `${config.token}:${config.service}`,
host: config.collector.hostname,
certificates: config.trustedpath ?? (config.appoptics ? certificate : ""),
grpc_proxy: config.proxy ?? "",
Expand Down
2 changes: 1 addition & 1 deletion packages/solarwinds-apm/src/appoptics/sampler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ import {
} from "@solarwinds-apm/sampling"

import { type Configuration } from "../config.js"
import { componentLogger } from "../logger.js"
import { HEADERS_STORAGE, traceParent } from "../propagation/headers.js"
import { Sampler } from "../sampling/sampler.js"
import { componentLogger } from "../shared/logger.js"

export class AppopticsSampler extends Sampler {
constructor(config: Configuration) {
Expand Down
Loading

0 comments on commit e9f17be

Please sign in to comment.