diff --git a/.gitignore b/.gitignore index 5059dd00fe84..9e8180493a46 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ assets/jsconfig.json # Webstorm /.idea/** + +.dart_tool +pubspec.lock diff --git a/.gitmodules b/.gitmodules index 9f0876759a63..55a63564f5f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,10 +2,11 @@ path = themes/docsy url = https://github.com/cncf/docsy.git docsy-pin = v0.9.0 + docsy-reminder = "Ensure that all tags from google/docsy are also present in cncf/docsy, otherwise add (push) them." [submodule "content-modules/opentelemetry-specification"] path = content-modules/opentelemetry-specification url = https://github.com/open-telemetry/opentelemetry-specification.git - spec-pin = v1.29.0 + spec-pin = v1.30.0 [submodule "content-modules/community"] path = content-modules/community url = https://github.com/open-telemetry/community @@ -22,3 +23,7 @@ path = content-modules/opamp-spec url = https://github.com/open-telemetry/opamp-spec opamp-pin = v0.8.0-5-g0360da8 +[submodule "content-modules/opentelemetry-go"] + path = content-modules/opentelemetry-go + url = https://github.com/open-telemetry/opentelemetry-go + go-pin = v1.23.0-rc.1-31-geabcef4c2 diff --git a/content-modules/opentelemetry-go b/content-modules/opentelemetry-go new file mode 160000 index 000000000000..eabcef4c2da6 --- /dev/null +++ b/content-modules/opentelemetry-go @@ -0,0 +1 @@ +Subproject commit eabcef4c2da6149b7e6dbbb8b7294402fcc287c1 diff --git a/content-modules/opentelemetry-specification b/content-modules/opentelemetry-specification index c6520a732870..5d9cef817415 160000 --- a/content-modules/opentelemetry-specification +++ b/content-modules/opentelemetry-specification @@ -1 +1 @@ -Subproject commit c6520a73287040ca16499cba62cea1b3508dc4da +Subproject commit 5d9cef817415a15aaa4883e184a38adec79096ed diff --git a/content/en/docs/concepts/signals/metrics.md b/content/en/docs/concepts/signals/metrics.md index 3f4ac360fb36..b71438ae0d5c 100644 --- a/content/en/docs/concepts/signals/metrics.md +++ b/content/en/docs/concepts/signals/metrics.md @@ -73,6 +73,10 @@ The instrument kind is one of the following: A histogram is a good choice if you are interested in value statistics. For example: How many requests take fewer than 1s? +For more on synchronous and asynchronous instruments, and which kind is best +suited for your use case, see +[Supplementary Guidelines](/docs/specs/otel/metrics/supplementary-guidelines/). + ## Aggregation In addition to the metric instruments, the concept of **aggregations** is an diff --git a/content/en/docs/languages/go/getting-started.md b/content/en/docs/languages/go/getting-started.md index c6488eacdb77..592fc0cb0893 100644 --- a/content/en/docs/languages/go/getting-started.md +++ b/content/en/docs/languages/go/getting-started.md @@ -5,6 +5,9 @@ weight: 10 cSpell:ignore: chan fatalln funcs intn itoa khtml otelhttp rolldice stdouttrace strconv --- + + + This page will show you how to get started with OpenTelemetry in Go. You will learn how you can instrument a simple application manually, in such a @@ -121,6 +124,8 @@ application that exports telemetry. Create `otel.go` with OpenTelemetry SDK bootstrapping code: + + ```go package main @@ -220,6 +225,7 @@ func newMeterProvider() (*metric.MeterProvider, error) { return meterProvider, nil } ``` + If you're only using tracing or metrics, you can omit the code the corresponding TracerProvider or MeterProvider initialization code. @@ -232,6 +238,8 @@ server. Modify `main.go` to include code that sets up OpenTelemetry SDK and instruments the HTTP server using the `otelhttp` instrumentation library: + + ```go package main @@ -317,6 +325,7 @@ func newHTTPHandler() http.Handler { return handler } ``` + ### Add Custom Instrumentation @@ -327,6 +336,8 @@ your application. For that you'll need to write some custom Modify `rolldice.go` to include custom instrumentation using OpenTelemetry API: + + ```go package main @@ -364,7 +375,6 @@ func rolldice(w http.ResponseWriter, r *http.Request) { roll := 1 + rand.Intn(6) - // Add the custom attribute to the span and counter. rollValueAttr := attribute.Int("roll.value", roll) span.SetAttributes(rollValueAttr) rollCnt.Add(ctx, 1, metric.WithAttributes(rollValueAttr)) @@ -375,6 +385,7 @@ func rolldice(w http.ResponseWriter, r *http.Request) { } } ``` + Note that if you're only using tracing or metrics, you can omit the corresponding code that instruments the other telemetry type. diff --git a/content/en/docs/languages/java/instrumentation.md b/content/en/docs/languages/java/instrumentation.md index 1512bdcb0378..f4d8a78a2168 100644 --- a/content/en/docs/languages/java/instrumentation.md +++ b/content/en/docs/languages/java/instrumentation.md @@ -674,7 +674,7 @@ automatically set by the OpenTelemetry SDK. The code below illustrates how to create a span: -```java { hl_lines=["1-2","8-11","19-21"] } +```java { hl_lines=["1-2","8-11","25-30"] } import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; diff --git a/content/en/docs/languages/js/instrumentation.md b/content/en/docs/languages/js/instrumentation.md index b44eeed549d2..a7362827294b 100644 --- a/content/en/docs/languages/js/instrumentation.md +++ b/content/en/docs/languages/js/instrumentation.md @@ -1192,30 +1192,10 @@ Node.js or Web SDKs. ## Metrics -To start producing [metrics](/docs/concepts/signals/metrics), you'll need to -have an initialized `MeterProvider` that lets you create a `Meter`. `Meter`s let -you create `Instrument`s that you can use to create different kinds of metrics. -OpenTelemetry JavaScript currently supports the following `Instrument`s: - -- Counter, a synchronous instrument that supports non-negative increments -- Asynchronous Counter, an asynchronous instrument which supports non-negative - increments -- Histogram, a synchronous instrument that supports arbitrary values that are - statistically meaningful, such as histograms, summaries, or percentile -- Asynchronous Gauge, an asynchronous instrument that supports non-additive - values, such as room temperature -- UpDownCounter, a synchronous instrument that supports increments and - decrements, such as the number of active requests -- Asynchronous UpDownCounter, an asynchronous instrument that supports - increments and decrements - -For more on synchronous and asynchronous instruments, and which kind is best -suited for your use case, see -[Supplementary Guidelines](/docs/specs/otel/metrics/supplementary-guidelines/). - -If a `MeterProvider` is not created either by an instrumentation library or -manually, the OpenTelemetry Metrics API will use a no-op implementation and fail -to generate data. +[Metrics](/docs/concepts/signals/metrics) combine individual measurements into +aggregates, and produce data which is constant as a function of system load. +Aggregates lack details required to diagnose low level issues, but complement +spans by helping to identify trends and providing application runtime telemetry. ### Initialize Metrics @@ -1275,9 +1255,8 @@ const resource = Resource.default().merge( const metricReader = new PeriodicExportingMetricReader({ exporter: new ConsoleMetricExporter(), - - // Default is 60000ms (60 seconds). Set to 3 seconds for demonstrative purposes only. - exportIntervalMillis: 3000, + // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. + exportIntervalMillis: 10000, }); const myServiceMeterProvider = new MeterProvider({ @@ -1314,8 +1293,8 @@ const resource = Resource.default().merge( const metricReader = new PeriodicExportingMetricReader({ exporter: new ConsoleMetricExporter(), - // Default is 60000ms (60 seconds). Set to 3 seconds for demonstrative purposes only. - exportIntervalMillis: 3000, + // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. + exportIntervalMillis: 10000, }); const myServiceMeterProvider = new MeterProvider({ @@ -1358,7 +1337,10 @@ call `getMeter` to acquire a meter. For example: ```ts import opentelemetry from '@opentelemetry/api'; -const myMeter = opentelemetry.metrics.getMeter('my-service-meter'); +const myMeter = opentelemetry.metrics.getMeter( + 'instrumentation-scope-name', + 'instrumentation-scope-version', +); // You can now use a 'meter' to create instruments! ``` @@ -1368,59 +1350,181 @@ const myMeter = opentelemetry.metrics.getMeter('my-service-meter'); ```js const opentelemetry = require('@opentelemetry/api'); -const myMeter = opentelemetry.metrics.getMeter('my-service-meter'); +const myMeter = opentelemetry.metrics.getMeter( + 'instrumentation-scope-name', + 'instrumentation-scope-version', +); // You can now use a 'meter' to create instruments! ``` {{% /tab %}} {{< /tabpane >}} +The values of `instrumentation-scope-name` and `instrumentation-scope-version` +should uniquely identify the +[Instrumentation Scope](/docs/concepts/instrumentation-scope/), such as the +package, module or class name. While the name is required, the version is still +recommended despite being optional. + It’s generally recommended to call `getMeter` in your app when you need it rather than exporting the meter instance to the rest of your app. This helps avoid trickier application load issues when other required dependencies are involved. -### Synchronous and asynchronous instruments +In the case of the [example app](#example-app), there are two places where a +tracer may be acquired with an appropriate Instrumentation Scope: -OpenTelemetry instruments are either synchronous or asynchronous (observable). +First, in the _application file_ `app.ts` (or `app.js`): -Synchronous instruments take a measurement when they are called. The measurement -is done as another call during program execution, just like any other function -call. Periodically, the aggregation of these measurements is exported by a -configured exporter. Because measurements are decoupled from exporting values, -an export cycle may contain zero or multiple aggregated measurements. +{{< tabpane text=true >}} {{% tab TypeScript %}} -Asynchronous instruments, on the other hand, provide a measurement at the -request of the SDK. When the SDK exports, a callback that was provided to the -instrument on creation is invoked. This callback provides the SDK with a -measurement that is immediately exported. All measurements on asynchronous -instruments are performed once per export cycle. +```ts +/*app.ts*/ +import { metrics, trace } from '@opentelemetry/api'; +import express, { Express } from 'express'; +import { rollTheDice } from './dice'; -Asynchronous instruments are useful in several circumstances, such as: +const tracer = trace.getTracer('dice-server', '0.1.0'); +const meter = metrics.getMeter('dice-server', '0.1.0'); -- When updating a counter is not computationally cheap, and you don't want the - current executing thread to wait for the measurement -- Observations need to happen at frequencies unrelated to program execution - (i.e., they cannot be accurately measured when tied to a request lifecycle) -- There is no known timestamp for a measurement value +const PORT: number = parseInt(process.env.PORT || '8080'); +const app: Express = express(); -In cases like these, it's often better to observe a cumulative value directly, -rather than aggregate a series of deltas in post-processing (the synchronous -example). Take note of the use of `observe` rather than `add` in the appropriate -code examples below. +app.get('/rolldice', (req, res) => { + const rolls = req.query.rolls ? parseInt(req.query.rolls.toString()) : NaN; + if (isNaN(rolls)) { + res + .status(400) + .send("Request parameter 'rolls' is missing or not a number."); + return; + } + res.send(JSON.stringify(rollTheDice(rolls, 1, 6))); +}); -### Using Counters +app.listen(PORT, () => { + console.log(`Listening for requests on http://localhost:${PORT}`); +}); +``` -Counters can be used to measure a non-negative, increasing value. +{{% /tab %}} {{% tab JavaScript %}} ```js -const counter = myMeter.createCounter('events.counter'); +/*app.js*/ +const { trace, metrics } = require('@opentelemetry/api'); +const express = require('express'); +const { rollTheDice } = require('./dice.js'); -//... +const tracer = trace.getTracer('dice-server', '0.1.0'); +const meter = metrics.getMeter('dice-server', '0.1.0'); -counter.add(1); +const PORT = parseInt(process.env.PORT || '8080'); +const app = express(); + +app.get('/rolldice', (req, res) => { + const rolls = req.query.rolls ? parseInt(req.query.rolls.toString()) : NaN; + if (isNaN(rolls)) { + res + .status(400) + .send("Request parameter 'rolls' is missing or not a number."); + return; + } + res.send(JSON.stringify(rollTheDice(rolls, 1, 6))); +}); + +app.listen(PORT, () => { + console.log(`Listening for requests on http://localhost:${PORT}`); +}); +``` + +{{% /tab %}} {{< /tabpane >}} + +And second, in the _library file_ `dice.ts` (or `dice.js`): + +{{< tabpane text=true >}} {{% tab TypeScript %}} + +```ts +/*dice.ts*/ +import { trace, metrics } from '@opentelemetry/api'; + +const tracer = trace.getTracer('dice-lib'); +const meter = metrics.getMeter('dice-lib'); + +function rollOnce(min: number, max: number) { + return Math.floor(Math.random() * (max - min) + min); +} + +export function rollTheDice(rolls: number, min: number, max: number) { + const result: number[] = []; + for (let i = 0; i < rolls; i++) { + result.push(rollOnce(min, max)); + } + return result; +} ``` +{{% /tab %}} {{% tab JavaScript %}} + +```js +/*dice.js*/ +const { trace, metrics } = require('@opentelemetry/api'); + +const tracer = trace.getTracer('dice-lib'); +const meter = metrics.getMeter('dice-lib'); + +function rollOnce(min, max) { + return Math.floor(Math.random() * (max - min) + min); +} + +function rollTheDice(rolls, min, max) { + const result = []; + for (let i = 0; i < rolls; i++) { + result.push(rollOnce(min, max)); + } + return result; +} + +module.exports = { rollTheDice }; +``` + +{{% /tab %}} {{< /tabpane >}} + +Now that you have [meters](/docs/concepts/signals/metrics/#meter) initialized. +you can create +[metric instruments](/docs/concepts/signals/metrics/#metric-instruments). + +### Create counters + +Counters can be used to measure a non-negative, increasing value. + +In the case of our [example app](#example-app) we can use this to count how +often the dice has been rolled: + +{{< tabpane text=true >}} {{% tab TypeScript %}} + +```ts +/*dice.ts*/ +const counter = meter.createCounter('dice-lib.rolls.counter'); + +function rollOnce(min: number, max: number) { + counter.add(1); + return Math.floor(Math.random() * (max - min) + min); +} +``` + +{{% /tab %}} {{% tab JavaScript %}} + +```js +/*dice.js*/ +const counter = meter.createCounter('dice-lib.rolls.counter'); + +function rollOnce(min, max) { + counter.add(1); + return Math.floor(Math.random() * (max - min) + min); +} +``` + +{{% /tab %}} {{< /tabpane >}} + ### Using UpDown Counters UpDown counters can increment and decrement, allowing you to observe a diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000000..72b6629df498 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,4 @@ +# Examples + +The files in this folder are used to extract code snippets that are used in the +docs. diff --git a/examples/go b/examples/go new file mode 120000 index 000000000000..2b8b80515257 --- /dev/null +++ b/examples/go @@ -0,0 +1 @@ +../content-modules/opentelemetry-go/example \ No newline at end of file diff --git a/package.json b/package.json index e19889c66484..6425b503bef6 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,9 @@ "check:text": "npm run _check:text -- ", "check": "npm run seq -- $(npm run -s _list:check:*)", "clean": "make clean", + "code-excerpts": "rm -Rf tmp/excerpts/* && npm run seq -- code-excerpts:get code-excerpts:update-docs", + "code-excerpts:get": "cd tools && dart run build_runner build --delete-conflicting-outputs --output ../tmp/excerpts", + "code-excerpts:update-docs": "cd tools && dart run code_excerpt_updater --fragment-dir-path ../tmp/excerpts --src-dir-path examples --yaml --write-in-place content", "cp:spec": "./scripts/content-modules/cp-pages.sh", "diff:check": "npm run _diff:check || (echo; echo 'WARNING: the files above have not been committed'; echo)", "diff:fail": "npm run _diff:check || (echo; echo 'ERROR: the files above have changed. Locally rerun `npm run test-and-fix` and commit changes'; echo; exit 1)", diff --git a/scripts/content-modules/adjust-pages.pl b/scripts/content-modules/adjust-pages.pl index a9003b91dc71..06d1d88823f6 100755 --- a/scripts/content-modules/adjust-pages.pl +++ b/scripts/content-modules/adjust-pages.pl @@ -18,7 +18,7 @@ my $semConvRef = "$otelSpecRepoUrl/blob/main/semantic_conventions/README.md"; my $specBasePath = '/docs/specs'; my %versions = qw( - spec: 1.29.0 + spec: 1.30.0 otlp: 1.1.0 semconv: 1.24.0 ); diff --git a/static/refcache.json b/static/refcache.json index e78f42be6dd4..16858776a05e 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -1411,6 +1411,10 @@ "StatusCode": 200, "LastSeen": "2024-01-18T19:02:11.609878-05:00" }, + "https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html": { + "StatusCode": 200, + "LastSeen": "2024-02-15T23:57:17.652434515Z" + }, "https://docs.otterize.com/reference/configuration/network-mapper/helm-chart#opentelemetry-exporter-parameters": { "StatusCode": 206, "LastSeen": "2024-01-30T16:15:20.577253-05:00" diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 000000000000..03eb645f1858 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,11 @@ +# Tools for handling code excerpts + +This directory contains the tooling, config, and data sources for managing code +excerpts. This functionality is currently experimental, and used only by site +maintainers. + +## Dependencies + +- **Dart**: for installation instructions, see [Get the Dart SDK]. + +[Get the Dart SDK]: https://dart.dev/get-dart diff --git a/tools/build.yaml b/tools/build.yaml new file mode 100644 index 000000000000..27e135172af4 --- /dev/null +++ b/tools/build.yaml @@ -0,0 +1,12 @@ +targets: + $default: + sources: + include: + - examples/** + # The following are included to avoid "required resources" tool warnings: + - $package$ + - lib/$lib$ + # exclude: ['**/.*/**'] + builders: + code_excerpter|code_excerpter: + enabled: true diff --git a/tools/content/go b/tools/content/go new file mode 120000 index 000000000000..aa64f4ef94b5 --- /dev/null +++ b/tools/content/go @@ -0,0 +1 @@ +../../content/en/docs/languages/go \ No newline at end of file diff --git a/tools/examples b/tools/examples new file mode 120000 index 000000000000..a6573af9c9da --- /dev/null +++ b/tools/examples @@ -0,0 +1 @@ +../examples \ No newline at end of file diff --git a/tools/pubspec.yaml b/tools/pubspec.yaml new file mode 100644 index 000000000000..f6fcf96b2545 --- /dev/null +++ b/tools/pubspec.yaml @@ -0,0 +1,16 @@ +name: otel_io_excerpts +publish_to: none + +environment: + sdk: ^3.2.0 + +dev_dependencies: + build_runner: ^2.4.6 + code_excerpter: + git: + url: https://github.com/chalin/site-shared + path: packages/code_excerpter + code_excerpt_updater: + git: + url: https://github.com/chalin/site-shared + path: packages/code_excerpt_updater