From 9f8c26f956df8042d80a8ab332edca679b1adb70 Mon Sep 17 00:00:00 2001 From: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:50:46 -0500 Subject: [PATCH 01/19] Auto-update registry versions (ce522a2c4f6df417c82c34fc4e77ce34cf5bbd03) (#5416) --- data/registry/instrumentation-js-prisma.yml | 2 +- data/registry/instrumentation-php-laravel.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/registry/instrumentation-js-prisma.yml b/data/registry/instrumentation-js-prisma.yml index 6e822eb2f803..fb463f9b2e15 100644 --- a/data/registry/instrumentation-js-prisma.yml +++ b/data/registry/instrumentation-js-prisma.yml @@ -17,5 +17,5 @@ createdAt: 2022-08-25 package: registry: npm name: '@prisma/instrumentation' - version: 5.20.0 + version: 5.21.0 isFirstParty: true diff --git a/data/registry/instrumentation-php-laravel.yml b/data/registry/instrumentation-php-laravel.yml index 1aaf1e2f4ace..bee5f2b34eec 100644 --- a/data/registry/instrumentation-php-laravel.yml +++ b/data/registry/instrumentation-php-laravel.yml @@ -15,5 +15,5 @@ createdAt: 2023-05-22 package: registry: packagist name: open-telemetry/opentelemetry-auto-laravel - version: 0.0.28 + version: 1.0.0 isFirstParty: false From 8a0737297dde435446ce1ec0b165eb7c93bb4e1b Mon Sep 17 00:00:00 2001 From: Vitor Vasconcellos Date: Wed, 16 Oct 2024 02:56:26 -0300 Subject: [PATCH 02/19] [pt] Initialize translations for /pt/docs/languages/go (#5346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marylia Gutierrez Co-authored-by: Marylia Gutierrez Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com> --- content/pt/docs/languages/go/_index.md | 15 + content/pt/docs/languages/go/api.md | 9 + content/pt/docs/languages/go/examples.md | 8 + .../pt/docs/languages/go/getting-started.md | 1177 +++++++++++++++++ layouts/partials/pt/docs/latest-release.md | 7 + .../pt/docs/languages/index-intro.md | 28 + 6 files changed, 1244 insertions(+) create mode 100644 content/pt/docs/languages/go/_index.md create mode 100644 content/pt/docs/languages/go/api.md create mode 100644 content/pt/docs/languages/go/examples.md create mode 100644 content/pt/docs/languages/go/getting-started.md create mode 100644 layouts/partials/pt/docs/latest-release.md create mode 100644 layouts/shortcodes/pt/docs/languages/index-intro.md diff --git a/content/pt/docs/languages/go/_index.md b/content/pt/docs/languages/go/_index.md new file mode 100644 index 000000000000..390662a5e28d --- /dev/null +++ b/content/pt/docs/languages/go/_index.md @@ -0,0 +1,15 @@ +--- +title: Go +description: >- + Go A language-specific implementation of OpenTelemetry in Go. +aliases: [/golang, /golang/metrics, /golang/tracing] +weight: 16 +default_lang_commit: 06837fe15457a584f6a9e09579be0f0400593d57 +--- + +{{% pt/docs/languages/index-intro go /%}} + +## Mais + +- [Repositório Contrib](https://github.com/open-telemetry/opentelemetry-go-contrib) diff --git a/content/pt/docs/languages/go/api.md b/content/pt/docs/languages/go/api.md new file mode 100644 index 000000000000..f241e1951cf5 --- /dev/null +++ b/content/pt/docs/languages/go/api.md @@ -0,0 +1,9 @@ +--- +title: Referências da API +linkTitle: API +redirect: https://pkg.go.dev/go.opentelemetry.io/otel +manualLinkTarget: _blank +_build: { render: link } +weight: 210 +default_lang_commit: 06837fe15457a584f6a9e09579be0f0400593d57 +--- diff --git a/content/pt/docs/languages/go/examples.md b/content/pt/docs/languages/go/examples.md new file mode 100644 index 000000000000..2865a43ff16f --- /dev/null +++ b/content/pt/docs/languages/go/examples.md @@ -0,0 +1,8 @@ +--- +title: Exemplos +redirect: https://github.com/open-telemetry/opentelemetry-go/tree/main/example +manualLinkTarget: _blank +_build: { render: link } +weight: 220 +default_lang_commit: 06837fe15457a584f6a9e09579be0f0400593d57 +--- diff --git a/content/pt/docs/languages/go/getting-started.md b/content/pt/docs/languages/go/getting-started.md new file mode 100644 index 000000000000..a794d812d46b --- /dev/null +++ b/content/pt/docs/languages/go/getting-started.md @@ -0,0 +1,1177 @@ +--- +title: Primeiros Passos +weight: 10 +default_lang_commit: 7fd0d2a6b87d6bbf2d5a35340c7afbd2bb33ca1c +# prettier-ignore +cSpell:ignore: chan fatalln funcs intn itoa khtml otelhttp rolldice stdouttrace strconv +--- + + + + +Esta página mostrará como começar a utilizar o OpenTelemetry em Go. + +Você aprenderá como instrumentar manualmente uma aplicação simples, de modo que +os [rastros][traces], [métricas][metrics] e [logs][logs] sejam emitidos no +console. + +{{% alert title="Note" %}} + +Os sinais de logs ainda são experimentais. Alterações que quebrem a +compatibilidade podem ser introduzidas em versões futuras. + +{{% /alert %}} + +## Pré-requisitos {#prerequisites} + +Certifique-se de que você tenha a seguinte instalação localmente: + +- [Go](https://go.dev/) versão 1.22 ou superior + +## Aplicação de exemplo {#example-application} + +O seguinte exemplo usa uma aplicação [`net/http`](https://pkg.go.dev/net/http) +básica. Caso você não esteja usando `net/http`, não há problema — você pode +utilizar OpenTelemetry Go com outros frameworks da web, como Gin e Echo. Para +uma lista completa de bibliotecas para frameworks suportados, consulte o +[registro](/ecosystem/registry/?component=instrumentation&language=go). + +Para exemplos mais elaborados, consulte +[exemplos](/docs/languages/go/examples/). + +### Configuração {#setup} + +Para começar, configure um `go.mod` em um novo diretório: + +```shell +go mod init dice +``` + +### Criar e iniciar um servidor HTTP {#create-and-launch-an-http-server} + +Na mesma pasta, crie um arquivo chamado `main.go` e adicione o seguinte código +ao arquivo: + +```go +package main + +import ( + "log" + "net/http" +) + +func main() { + http.HandleFunc("/rolldice", rolldice) + + log.Fatal(http.ListenAndServe(":8080", nil)) +} +``` + +Crie outro arquivo chamado `rolldice.go` e adicione o seguinte código ao +arquivo: + +```go +package main + +import ( + "io" + "log" + "math/rand" + "net/http" + "strconv" +) + +func rolldice(w http.ResponseWriter, r *http.Request) { + roll := 1 + rand.Intn(6) + + resp := strconv.Itoa(roll) + "\n" + if _, err := io.WriteString(w, resp); err != nil { + log.Printf("Write failed: %v\n", err) + } +} +``` + +Compile e execute a aplicação utilizando o seguinte comando: + +```shell +go run . +``` + +Abra no seu navegador para garantir que está +funcionando. + +## Adicionar instrumentação do OpenTelemetry {#add-open-telemetry-instrumentation} + +Agora, vamos mostrar como adicionar instrumentação do OpenTelemetry à aplicação +de exemplo. Se você estiver usando sua própria aplicação, também pode acompanhar +os passos a seguir. Apenas note que seu código pode ser um pouco diferente do +exemplo. + +### Adicionar Dependências {#add-dependencies} + +Instale os seguintes pacotes: + +```shell +go get "go.opentelemetry.io/otel" \ + "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" \ + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" \ + "go.opentelemetry.io/otel/exporters/stdout/stdoutlog" \ + "go.opentelemetry.io/otel/sdk/log" \ + "go.opentelemetry.io/otel/log/global" \ + "go.opentelemetry.io/otel/propagation" \ + "go.opentelemetry.io/otel/sdk/metric" \ + "go.opentelemetry.io/otel/sdk/resource" \ + "go.opentelemetry.io/otel/sdk/trace" \ + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"\ + "go.opentelemetry.io/contrib/bridges/otelslog" +``` + +Este comando instala os componentes do SDK OpenTelemetry e a instrumentação do +`net/http`. + +Se você estiver instrumentando uma biblioteca diferente para solicitações de +rede, precisará instalar a biblioteca de instrumentação apropriada. Consulte a +seção [bibliotecas](/docs/languages/go/libraries/) para mais informações. + +### Inicializar o SDK OpenTelemetry {#initialize-the-opentelemetry-sdk} + +Primeiro, vamos inicializar o SDK OpenTelemetry. Isso é _obrigatório_ para +qualquer aplicação que exporte telemetria. + +Crie um arquivo `otel.go` com o código de inicialização do SDK OpenTelemetry: + + + +```go +package main + +import ( + "context" + "errors" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/stdout/stdoutlog" + "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + "go.opentelemetry.io/otel/log/global" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/log" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/trace" +) + +// setupOTelSDK inicializa o pipeline do OpenTelemetry. +// Caso não retorne um erro, certifique-se de executar o método shutdown para realizar a finalização adequada. +func setupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, err error) { + var shutdownFuncs []func(context.Context) error + + // shutdown chama as funções de finalização registradas via shutdownFuncs. + // Os erros das chamadas são concatenados. + // Cada função de finalização registrada será invocada uma única vez. + shutdown = func(ctx context.Context) error { + var err error + for _, fn := range shutdownFuncs { + err = errors.Join(err, fn(ctx)) + } + shutdownFuncs = nil + return err + } + + // handleErr chama a função shutdown para finalizar corretamente e garante que todos os erros serão retornados. + handleErr := func(inErr error) { + err = errors.Join(inErr, shutdown(ctx)) + } + + // Inicializa o Propagator. + prop := newPropagator() + otel.SetTextMapPropagator(prop) + + // Inicializa o Trace Provider. + tracerProvider, err := newTraceProvider() + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) + otel.SetTracerProvider(tracerProvider) + + // Inicializa o Meter Provider. + meterProvider, err := newMeterProvider() + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) + otel.SetMeterProvider(meterProvider) + + // Inicializa o Logger Provider. + loggerProvider, err := newLoggerProvider() + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, loggerProvider.Shutdown) + global.SetLoggerProvider(loggerProvider) + + return +} + +func newPropagator() propagation.TextMapPropagator { + return propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, + propagation.Baggage{}, + ) +} + +func newTraceProvider() (*trace.TracerProvider, error) { + traceExporter, err := stdouttrace.New( + stdouttrace.WithPrettyPrint()) + if err != nil { + return nil, err + } + + traceProvider := trace.NewTracerProvider( + trace.WithBatcher(traceExporter, + // O valor padrão é 5s. Definimos em 1s para propósito de demonstração. + trace.WithBatchTimeout(time.Second)), + ) + return traceProvider, nil +} + +func newMeterProvider() (*metric.MeterProvider, error) { + metricExporter, err := stdoutmetric.New() + if err != nil { + return nil, err + } + + meterProvider := metric.NewMeterProvider( + metric.WithReader(metric.NewPeriodicReader(metricExporter, + // O valor padrão é 1m. Definimos em 3s para propósito de demonstração. + metric.WithInterval(3*time.Second))), + ) + return meterProvider, nil +} + +func newLoggerProvider() (*log.LoggerProvider, error) { + logExporter, err := stdoutlog.New() + if err != nil { + return nil, err + } + + loggerProvider := log.NewLoggerProvider( + log.WithProcessor(log.NewBatchProcessor(logExporter)), + ) + return loggerProvider, nil +} +``` + + +Caso você esteja utilizando apenas rastros ou métricas, você pode omitir o +código de inicialização do TracerProvider ou MeterProvider correspondente. + +### Instrumentação do servidor HTTP {#instrument-the-http-server} + +Agora que temos o SDK do OpenTelemetry inicializado, podemos instrumentar o +servidor HTTP. + +Modifique o arquivo `main.go` para incluir o código que configura o SDK do +OpenTelemetry e instrumenta o servidor HTTP utilizando a biblioteca de +instrumentação `otelhttp`: + + + +```go +package main + +import ( + "context" + "errors" + "log" + "net" + "net/http" + "os" + "os/signal" + "time" + + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" +) + +func main() { + if err := run(); err != nil { + log.Fatalln(err) + } +} + +func run() (err error) { + // Lidamos com o SIGINT (CTRL+C) de maneira segura. + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) + defer stop() + + // Configura o OpenTelemetry. + otelShutdown, err := setupOTelSDK(ctx) + if err != nil { + return + } + // Lidamos com a finalização corretamente, evitando leaks. + defer func() { + err = errors.Join(err, otelShutdown(context.Background())) + }() + + // Inicializamos o servidor HTTP. + srv := &http.Server{ + Addr: ":8080", + BaseContext: func(_ net.Listener) context.Context { return ctx }, + ReadTimeout: time.Second, + WriteTimeout: 10 * time.Second, + Handler: newHTTPHandler(), + } + srvErr := make(chan error, 1) + go func() { + srvErr <- srv.ListenAndServe() + }() + + // Aguardamos por uma interrupção. + select { + case err = <-srvErr: + // Erro ao inicializar o servidor HTTP. + return + case <-ctx.Done(): + // Aguardamos o primeiro CTRL+C. + // Para de receber sinais o mais rápido possível. + stop() + } + + // Quando o método Shutdown é chamado, ListenAndServe retornará imediatamente ErrServerClosed. + err = srv.Shutdown(context.Background()) + return +} + +func newHTTPHandler() http.Handler { + mux := http.NewServeMux() + + // handleFunc é uma substituição para mux.HandleFunc + // enriquecendo ainda mais a instrumentação HTTP utilizando padrões como http.route. + handleFunc := func(pattern string, handlerFunc func(http.ResponseWriter, *http.Request)) { + // Configura o "http.route" para a instrumentação HTTP. + handler := otelhttp.WithRouteTag(pattern, http.HandlerFunc(handlerFunc)) + mux.Handle(pattern, handler) + } + + // Registra os handlers. + handleFunc("/rolldice/", rolldice) + handleFunc("/rolldice/{player}", rolldice) + + // Adiciona a instrumentação HTTP para todo o servidor. + handler := otelhttp.NewHandler(mux, "/") + return handler +} +``` + + +### Adicionar instrumentação personalizada {#add-custom-instrumentation} + +As bibliotecas de instrumentação capturam telemetria nas bordas de seus +sistemas, como por exemplo requisições HTTP de entrada e saída, porém não +capturam o que está acontecendo dentro da sua aplicação. Para isso, você +precisará implementar uma [instrumentação manual](../instrumentation/) +personalizada. + +Modifique o arquivo `rolldice.go` para incluir instrumentação personalizada +usando a API do OpenTelemetry: + + + +```go +package main + +import ( + "fmt" + "io" + "log" + "math/rand" + "net/http" + "strconv" + + "go.opentelemetry.io/contrib/bridges/otelslog" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +const name = "go.opentelemetry.io/otel/example/dice" + +var ( + tracer = otel.Tracer(name) + meter = otel.Meter(name) + logger = otelslog.NewLogger(name) + rollCnt metric.Int64Counter +) + +func init() { + var err error + rollCnt, err = meter.Int64Counter("dice.rolls", + metric.WithDescription("O número de lançamentos por valor obtido"), + metric.WithUnit("{roll}")) + if err != nil { + panic(err) + } +} + +func rolldice(w http.ResponseWriter, r *http.Request) { + ctx, span := tracer.Start(r.Context(), "roll") + defer span.End() + + roll := 1 + rand.Intn(6) + + var msg string + if player := r.PathValue("player"); player != "" { + msg = fmt.Sprintf("%s está lançando o dado", player) + } else { + msg = "Jogador anônimo está lançando o dado" + } + logger.InfoContext(ctx, msg, "result", roll) + + rollValueAttr := attribute.Int("roll.value", roll) + span.SetAttributes(rollValueAttr) + rollCnt.Add(ctx, 1, metric.WithAttributes(rollValueAttr)) + + resp := strconv.Itoa(roll) + "\n" + if _, err := io.WriteString(w, resp); err != nil { + log.Printf("Falha na escrita: %v\n", err) + } +} +``` + + +Observe que caso você esteja utilizando apenas rastros ou métricas, poderá +omitir o código de instrumentação correspondente ao componente que não está +sendo utilizado. + +### Executando a Aplicação {#run-the-application} + +Compile e execute a aplicação utilizando o seguinte comando: + +```sh +go mod tidy +export OTEL_RESOURCE_ATTRIBUTES="service.name=dice,service.version=0.1.0" +go run . +``` + +Abra no seu navegador. Ao enviar uma +solicitação para o servidor, você verá dois trechos no rastro emitido no +console. O trecho gerado pela biblioteca de instrumentação rastreia a duração da +solicitação para a rota `/rolldice/{player}`. O trecho chamado `roll` é criado +manualmente e é um filho do trecho mencionado anteriormente. + +
+Visualizar exemplo de saída + +```json +{ + "Name": "roll", + "SpanContext": { + "TraceID": "829fb7ceb787403c96eac3caf285c965", + "SpanID": "8b6b408b6c1a35e5", + "TraceFlags": "01", + "TraceState": "", + "Remote": false + }, + "Parent": { + "TraceID": "829fb7ceb787403c96eac3caf285c965", + "SpanID": "612be4bbdf450de6", + "TraceFlags": "01", + "TraceState": "", + "Remote": false + }, + "SpanKind": 1, + "StartTime": "2023-09-25T12:42:06.177119576+02:00", + "EndTime": "2023-09-25T12:42:06.177136776+02:00", + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 6 + } + } + ], + "Events": null, + "Links": null, + "Status": { + "Code": "Unset", + "Description": "" + }, + "DroppedAttributes": 0, + "DroppedEvents": 0, + "DroppedLinks": 0, + "ChildSpanCount": 0, + "Resource": [ + { + "Key": "service.name", + "Value": { + "Type": "STRING", + "Value": "dice" + } + }, + { + "Key": "service.version", + "Value": { + "Type": "STRING", + "Value": "0.1.0" + } + }, + { + "Key": "telemetry.sdk.language", + "Value": { + "Type": "STRING", + "Value": "go" + } + }, + { + "Key": "telemetry.sdk.name", + "Value": { + "Type": "STRING", + "Value": "opentelemetry" + } + }, + { + "Key": "telemetry.sdk.version", + "Value": { + "Type": "STRING", + "Value": "1.19.0-rc.1" + } + } + ], + "InstrumentationLibrary": { + "Name": "rolldice", + "Version": "", + "SchemaURL": "" + } +} +{ + "Name": "/", + "SpanContext": { + "TraceID": "829fb7ceb787403c96eac3caf285c965", + "SpanID": "612be4bbdf450de6", + "TraceFlags": "01", + "TraceState": "", + "Remote": false + }, + "Parent": { + "TraceID": "00000000000000000000000000000000", + "SpanID": "0000000000000000", + "TraceFlags": "00", + "TraceState": "", + "Remote": false + }, + "SpanKind": 2, + "StartTime": "2023-09-25T12:42:06.177071077+02:00", + "EndTime": "2023-09-25T12:42:06.177158076+02:00", + "Attributes": [ + { + "Key": "http.method", + "Value": { + "Type": "STRING", + "Value": "GET" + } + }, + { + "Key": "http.scheme", + "Value": { + "Type": "STRING", + "Value": "http" + } + }, + { + "Key": "http.flavor", + "Value": { + "Type": "STRING", + "Value": "1.1" + } + }, + { + "Key": "net.host.name", + "Value": { + "Type": "STRING", + "Value": "localhost" + } + }, + { + "Key": "net.host.port", + "Value": { + "Type": "INT64", + "Value": 8080 + } + }, + { + "Key": "net.sock.peer.addr", + "Value": { + "Type": "STRING", + "Value": "::1" + } + }, + { + "Key": "net.sock.peer.port", + "Value": { + "Type": "INT64", + "Value": 49046 + } + }, + { + "Key": "http.user_agent", + "Value": { + "Type": "STRING", + "Value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" + } + }, + { + "Key": "http.route", + "Value": { + "Type": "STRING", + "Value": "/rolldice/Alice" + } + }, + { + "Key": "http.wrote_bytes", + "Value": { + "Type": "INT64", + "Value": 2 + } + }, + { + "Key": "http.status_code", + "Value": { + "Type": "INT64", + "Value": 200 + } + } + ], + "Events": null, + "Links": null, + "Status": { + "Code": "Unset", + "Description": "" + }, + "DroppedAttributes": 0, + "DroppedEvents": 0, + "DroppedLinks": 0, + "ChildSpanCount": 1, + "Resource": [ + { + "Key": "service.name", + "Value": { + "Type": "STRING", + "Value": "dice" + } + }, + { + "Key": "service.version", + "Value": { + "Type": "STRING", + "Value": "0.1.0" + } + }, + { + "Key": "telemetry.sdk.language", + "Value": { + "Type": "STRING", + "Value": "go" + } + }, + { + "Key": "telemetry.sdk.name", + "Value": { + "Type": "STRING", + "Value": "opentelemetry" + } + }, + { + "Key": "telemetry.sdk.version", + "Value": { + "Type": "STRING", + "Value": "1.19.0-rc.1" + } + } + ], + "InstrumentationLibrary": { + "Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", + "Version": "0.44.0", + "SchemaURL": "" + } +} +``` + +
+ +Junto com o rastro, mensagens de log são emitidas no console. + +
+Visualizar exemplo de saída + +```json +{ + "Timestamp": "2023-09-25T12:42:05.177136776+02:00", + "ObservedTimestamp": "2023-09-25T12:42:06.809396011+02:00", + "Severity": 9, + "SeverityText": "", + "Body": { + "Type": "String", + "Value": "Alice está lançando o dado" + }, + "Attributes": [ + { + "Key": "result", + "Value": { + "Type": "Int64", + "Value": 6 + } + } + ], + "TraceID": "829fb7ceb787403c96eac3caf285c965", + "SpanID": "8b6b408b6c1a35e5", + "TraceFlags": "01", + "Resource": [ + { + "Key": "service.name", + "Value": { + "Type": "STRING", + "Value": "dice" + } + }, + { + "Key": "service.version", + "Value": { + "Type": "STRING", + "Value": "0.1.0" + } + }, + { + "Key": "telemetry.sdk.language", + "Value": { + "Type": "STRING", + "Value": "go" + } + }, + { + "Key": "telemetry.sdk.name", + "Value": { + "Type": "STRING", + "Value": "opentelemetry" + } + }, + { + "Key": "telemetry.sdk.version", + "Value": { + "Type": "STRING", + "Value": "1.19.0-rc.1" + } + } + ], + "Scope": { + "Name": "rolldice", + "Version": "", + "SchemaURL": "" + }, + "DroppedAttributes": 0 +} +``` + +
+ +Atualize a página algumas vezes, e então +você pode esperar um pouco ou encerrar a execução da aplicação e verá as +métricas como na saída do console. Você verá a métrica `dice.rolls` emitida no +console, com contagens distintas para cada valor obtido, bem como as métricas +HTTP geradas pela biblioteca de instrumentação. + +
+Visualizar exemplo de saída + +```json +{ + "Resource": [ + { + "Key": "service.name", + "Value": { + "Type": "STRING", + "Value": "dice" + } + }, + { + "Key": "service.version", + "Value": { + "Type": "STRING", + "Value": "0.1.0" + } + }, + { + "Key": "telemetry.sdk.language", + "Value": { + "Type": "STRING", + "Value": "go" + } + }, + { + "Key": "telemetry.sdk.name", + "Value": { + "Type": "STRING", + "Value": "opentelemetry" + } + }, + { + "Key": "telemetry.sdk.version", + "Value": { + "Type": "STRING", + "Value": "1.19.0-rc.1" + } + } + ], + "ScopeMetrics": [ + { + "Scope": { + "Name": "rolldice", + "Version": "", + "SchemaURL": "" + }, + "Metrics": [ + { + "Name": "dice.rolls", + "Description": "Número de lançamentos por valor obtido", + "Unit": "{roll}", + "Data": { + "DataPoints": [ + { + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 1 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279204638+02:00", + "Time": "2023-09-25T12:42:15.482694258+02:00", + "Value": 4 + }, + { + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 5 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279204638+02:00", + "Time": "2023-09-25T12:42:15.482694258+02:00", + "Value": 3 + }, + { + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 3 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279204638+02:00", + "Time": "2023-09-25T12:42:15.482694258+02:00", + "Value": 4 + }, + { + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 2 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279204638+02:00", + "Time": "2023-09-25T12:42:15.482694258+02:00", + "Value": 2 + }, + { + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 6 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279204638+02:00", + "Time": "2023-09-25T12:42:15.482694258+02:00", + "Value": 5 + }, + { + "Attributes": [ + { + "Key": "roll.value", + "Value": { + "Type": "INT64", + "Value": 4 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279204638+02:00", + "Time": "2023-09-25T12:42:15.482694258+02:00", + "Value": 9 + } + ], + "Temporality": "CumulativeTemporality", + "IsMonotonic": true + } + } + ] + }, + { + "Scope": { + "Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", + "Version": "0.44.0", + "SchemaURL": "" + }, + "Metrics": [ + { + "Name": "http.server.request_content_length", + "Description": "", + "Unit": "", + "Data": { + "DataPoints": [ + { + "Attributes": [ + { + "Key": "http.flavor", + "Value": { + "Type": "STRING", + "Value": "1.1" + } + }, + { + "Key": "http.method", + "Value": { + "Type": "STRING", + "Value": "GET" + } + }, + { + "Key": "http.route", + "Value": { + "Type": "STRING", + "Value": "/rolldice/Alice" + } + }, + { + "Key": "http.scheme", + "Value": { + "Type": "STRING", + "Value": "http" + } + }, + { + "Key": "http.status_code", + "Value": { + "Type": "INT64", + "Value": 200 + } + }, + { + "Key": "net.host.name", + "Value": { + "Type": "STRING", + "Value": "localhost" + } + }, + { + "Key": "net.host.port", + "Value": { + "Type": "INT64", + "Value": 8080 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279212238+02:00", + "Time": "2023-09-25T12:42:15.482695758+02:00", + "Value": 0 + } + ], + "Temporality": "CumulativeTemporality", + "IsMonotonic": true + } + }, + { + "Name": "http.server.response_content_length", + "Description": "", + "Unit": "", + "Data": { + "DataPoints": [ + { + "Attributes": [ + { + "Key": "http.flavor", + "Value": { + "Type": "STRING", + "Value": "1.1" + } + }, + { + "Key": "http.method", + "Value": { + "Type": "STRING", + "Value": "GET" + } + }, + { + "Key": "http.route", + "Value": { + "Type": "STRING", + "Value": "/rolldice/Alice" + } + }, + { + "Key": "http.scheme", + "Value": { + "Type": "STRING", + "Value": "http" + } + }, + { + "Key": "http.status_code", + "Value": { + "Type": "INT64", + "Value": 200 + } + }, + { + "Key": "net.host.name", + "Value": { + "Type": "STRING", + "Value": "localhost" + } + }, + { + "Key": "net.host.port", + "Value": { + "Type": "INT64", + "Value": 8080 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279214438+02:00", + "Time": "2023-09-25T12:42:15.482696158+02:00", + "Value": 54 + } + ], + "Temporality": "CumulativeTemporality", + "IsMonotonic": true + } + }, + { + "Name": "http.server.duration", + "Description": "", + "Unit": "", + "Data": { + "DataPoints": [ + { + "Attributes": [ + { + "Key": "http.flavor", + "Value": { + "Type": "STRING", + "Value": "1.1" + } + }, + { + "Key": "http.method", + "Value": { + "Type": "STRING", + "Value": "GET" + } + }, + { + "Key": "http.route", + "Value": { + "Type": "STRING", + "Value": "/rolldice/Alice" + } + }, + { + "Key": "http.scheme", + "Value": { + "Type": "STRING", + "Value": "http" + } + }, + { + "Key": "http.status_code", + "Value": { + "Type": "INT64", + "Value": 200 + } + }, + { + "Key": "net.host.name", + "Value": { + "Type": "STRING", + "Value": "localhost" + } + }, + { + "Key": "net.host.port", + "Value": { + "Type": "INT64", + "Value": 8080 + } + } + ], + "StartTime": "2023-09-25T12:42:04.279219438+02:00", + "Time": "2023-09-25T12:42:15.482697158+02:00", + "Count": 27, + "Bounds": [ + 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, + 7500, 10000 + ], + "BucketCounts": [ + 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], + "Min": {}, + "Max": {}, + "Sum": 2.1752759999999993 + } + ], + "Temporality": "CumulativeTemporality" + } + } + ] + } + ] +} +``` + +
+ +## Próximos passos {#next-steps} + +Para mais informações sobre como instrumentar seu código, consulte a +documentação de [instrumentação manual](/docs/languages/go/instrumentation/). + +Você também vai querer configurar um Exporter apropriado para +[exportar os seus dados de telemetria](/docs/languages/go/exporters/) para um ou +mais backends de telemetria. + +Caso queira explorar um exemplo mais complexo, dê uma olhada na +[demonstração do OpenTelemetry](/docs/demo/), que inclui o +[Serviço de Checkout](/docs/demo/services/checkout/), o +[Serviço de Catálogo de Produtos](/docs/demo/services/product-catalog/), e o +[Serviço de Contabilidade](/docs/demo/services/accounting/), baseados em Go + +[traces]: /docs/concepts/signals/traces/ +[metrics]: /docs/concepts/signals/metrics/ +[logs]: /docs/concepts/signals/logs/ diff --git a/layouts/partials/pt/docs/latest-release.md b/layouts/partials/pt/docs/latest-release.md new file mode 100644 index 000000000000..26df2998e6e3 --- /dev/null +++ b/layouts/partials/pt/docs/latest-release.md @@ -0,0 +1,7 @@ +{{ $relUrl := printf "https://github.com/open-telemetry/opentelemetry-%s/releases" .lang -}} + +Para lançamentos, incluindo a [última versão][latest release], consulte a página de [Lançamentos][Releases]. +{{- .Inner }} + +[latest release]: {{ $relUrl }}/latest +[Releases]: {{ $relUrl }} diff --git a/layouts/shortcodes/pt/docs/languages/index-intro.md b/layouts/shortcodes/pt/docs/languages/index-intro.md new file mode 100644 index 000000000000..0492c4e57401 --- /dev/null +++ b/layouts/shortcodes/pt/docs/languages/index-intro.md @@ -0,0 +1,28 @@ +{{/* +default_lang_commit: 2e21274a01a24a62c67595591d8f4255bef640fc +*/ -}} +{{ $prettier_ignore := ` + + +` -}} +{{ $lang := .Get 0 -}} +{{ $data := index $.Site.Data.instrumentation $lang }} +{{ $name := $data.name -}} + +{{ $tracesStatus := partial "docs/get-signal-status.html" (dict "lang" $lang "signal" "traces") -}} +{{ $metricsStatus := partial "docs/get-signal-status.html" (dict "lang" $lang "signal" "metrics") -}} +{{ $logsStatus := partial "docs/get-signal-status.html" (dict "lang" $lang "signal" "logs") -}} + +Esta é a documentação do OpenTelemetry para a linguagem {{ $name }}. O OpenTelemetry é um +framework de observabilidade -- API, SDKs, e ferramentas que são desenvolvidas para auxiliar na +geração e coleta de dados de telemetria de aplicações, como métricas, logs e rastros. Esta documentação foi criada para te auxiliar a entender como começar a utilizar o OpenTelemetry em {{ $name }}. + +## Estado e Lançamentos + +O estado atual dos principais componentes funcionais do OpenTelemetry para {{ $name }} é o seguinte: + +| Rastros | Métricas | Logs | +| ------------------- | -------------------- | ----------------- | +| {{ $tracesStatus }} | {{ $metricsStatus }} | {{ $logsStatus }} | + +{{ partial "pt/docs/latest-release.md" (dict "lang" $lang "Inner" .Inner) -}} From f6fc33361e80f51342ada4358d41780b685367a2 Mon Sep 17 00:00:00 2001 From: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Date: Wed, 16 Oct 2024 01:11:35 -0500 Subject: [PATCH 03/19] Update semantic-conventions-java version to v1.28.0 (#5411) --- content/en/docs/languages/java/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/languages/java/_index.md b/content/en/docs/languages/java/_index.md index e69686567dad..36a40f27de57 100644 --- a/content/en/docs/languages/java/_index.md +++ b/content/en/docs/languages/java/_index.md @@ -9,7 +9,7 @@ cascade: instrumentation: 2.8.0 otel: 1.43.0 contrib: 1.38.0 - semconv: 1.27.0 + semconv: 1.28.0 weight: 18 --- From b2d1ff550b77c37e15df502b8ef4e34204169ad1 Mon Sep 17 00:00:00 2001 From: Severin Neumann Date: Wed, 16 Oct 2024 09:13:09 +0200 Subject: [PATCH 04/19] Add guidelines for starting new localizations (#5385) Signed-off-by: svrnm Signed-off-by: svrnm Co-authored-by: Fabrizio Ferri-Benedetti --- content/en/docs/contributing/localization.md | 50 +++++++++++++++----- static/refcache.json | 8 ++++ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/content/en/docs/contributing/localization.md b/content/en/docs/contributing/localization.md index 4a88cc7f00ec..f1a25fd11505 100644 --- a/content/en/docs/contributing/localization.md +++ b/content/en/docs/contributing/localization.md @@ -204,22 +204,50 @@ For more details about the script, run `npm run check:i18n -- -h`. ## New localizations -(Section To Be Completed soon with information about how to propose a new -localization.) +To start a new localization for the OpenTelemetry website, +[raise an issue](https://github.com/open-telemetry/opentelemetry.io/issues/) to +share your interest to contribute. Tag all other individuals that are willing to +write and review translations in the language you want to add. You need at least +two potential contributors, three would be ideal. Include the following task +list in your issue as well: - +You don't have to be an existing contributor to the OpenTelemetry project, to +start a new localization. However you will not be added as a member of the +[OpenTelemetry GitHub organization](https://github.com/open-telemetry/) or as a +member of the approvers group for your localization. You will need to satisfy +the requirements for becoming an established member and approver as outlined in +the +[membership guidelines](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md). + +When starting the localization project, maintainers will treat your reviews as +if you are an approver already. + +{{% /alert %}} [main]: https://github.com/open-telemetry/opentelemetry.io/commits/main/ [multilingual framework]: https://gohugo.io/content-management/multilingual/ diff --git a/static/refcache.json b/static/refcache.json index 799529e377a0..012934c7f4f2 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -3435,6 +3435,10 @@ "StatusCode": 200, "LastSeen": "2024-01-18T19:02:13.980094-05:00" }, + "https://en.wikipedia.org/wiki/ISO_639-1": { + "StatusCode": 200, + "LastSeen": "2024-10-11T11:10:12.725968+02:00" + }, "https://en.wikipedia.org/wiki/In-band_signaling": { "StatusCode": 200, "LastSeen": "2024-01-18T19:01:54.201621-05:00" @@ -7179,6 +7183,10 @@ "StatusCode": 200, "LastSeen": "2024-06-13T15:48:00.42543+02:00" }, + "https://github.com/open-telemetry/opentelemetry.io/issues/": { + "StatusCode": 200, + "LastSeen": "2024-10-11T11:10:11.918895+02:00" + }, "https://github.com/open-telemetry/opentelemetry.io/issues/4427": { "StatusCode": 200, "LastSeen": "2024-05-06T15:32:24.49099-04:00" From 737ff895cf3e0d2b66d7a9f9ebdf23714e38387e Mon Sep 17 00:00:00 2001 From: Hans Kristian Flaatten Date: Wed, 16 Oct 2024 09:18:04 +0200 Subject: [PATCH 05/19] Add NAV - Norwegian Government to adopters.yaml (#5414) Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Severin Neumann --- data/ecosystem/adopters.yaml | 6 ++++++ static/refcache.json | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/data/ecosystem/adopters.yaml b/data/ecosystem/adopters.yaml index a7adc8bdcf23..f8d243799426 100644 --- a/data/ecosystem/adopters.yaml +++ b/data/ecosystem/adopters.yaml @@ -69,6 +69,12 @@ reference: 'https://medium.com/mercadolibre-tech/building-a-large-scale-observability-ecosystem-1edf654b249e' referenceTitle: blog post contact: 'https://github.com/mercadolibre' +- name: NAV - Norwegian Government + url: https://nav.no + components: [Collector, Go, Java, JavaScript, Python] + reference: 'https://nais.io/blog/posts/otel-from-0-to-100/' + referenceTitle: blog post + contact: 'https://github.com/Starefossen' - name: OrderMyGear url: https://www.ordermygear.com/ components: [] diff --git a/static/refcache.json b/static/refcache.json index 012934c7f4f2..9fc02794914b 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -9207,6 +9207,10 @@ "StatusCode": 200, "LastSeen": "2024-01-18T19:02:19.249572-05:00" }, + "https://nais.io/blog/posts/otel-from-0-to-100/": { + "StatusCode": 206, + "LastSeen": "2024-10-16T06:19:11.246616643Z" + }, "https://netlify.com": { "StatusCode": 206, "LastSeen": "2024-06-12T11:21:36.089536+02:00" From f9382f7aa7db68bb67dbe6bf289e5782cea3dc33 Mon Sep 17 00:00:00 2001 From: Damien Mathieu <42@dmathieu.com> Date: Wed, 16 Oct 2024 10:21:05 +0200 Subject: [PATCH 06/19] Add what is opentelemetry page in french (#5408) Co-authored-by: Pierre HILBERT --- .cspell/fr-mots.txt | 166 ++++++++++++++++++++++- content/fr/docs/what-is-opentelemetry.md | 133 ++++++++++++++++++ 2 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 content/fr/docs/what-is-opentelemetry.md diff --git a/.cspell/fr-mots.txt b/.cspell/fr-mots.txt index 24bf98df272d..7970e82b0e43 100644 --- a/.cspell/fr-mots.txt +++ b/.cspell/fr-mots.txt @@ -46,4 +46,168 @@ universelle utilisé visuel votre -vous \ No newline at end of file +vous +l'état +système +incluent +rendre +signifie +émettre +metriques +produites +doivent +transmises +Pourquoi +l'essor +commerciales +besoin +répond +suivant +principes +clés +propriétaire +générez +dépendance +fournisseur +n'avez +d'apprendre +seul +combinés +offrent +équipes +organisations +flexibilité +dont +informatique +Extensibilité +conçu +extensible +Quelques +façon +étendu +Ajouter +receveur +Collecteur +afin +prendre +venant +personnalisée +bibliothèques +personnalisées +Créer +collecteur +adaptée +utilisation +spécifique +nouvel +exportateur +personnalisé +prend +propagateur +contexte +plupart +utilisateurs +n'aient +d'étendre +presque +tous +niveaux +Histoire +trouve +antérieurs +créés +résoudre +même +problème +norme +décrivant +manière +transmettre +Aucun +n'étant +indépendante +fusionné +leurs +offrant +utilisez +actuellement +pouvez +découvrir +migrer +ensuite +commencer +Lancez +directement +composants +standardisé +définissant +sémantiques +décrire +langage +implémentent +spécifications +écosystème +instrumentent +automatique +génèrent +requérir +reçoit +modifie +autre +Opérateur +ressources +Faas +variété +intègrent +fournir +défaut +pris +fournisseurs +fournissent +contribuent +n’aient +d’étendre +conçus +créer +gérer +telles +outil +compris +ainsi +commerciaux +d'autres +génération +collecte +gestion +objectifs +principaux +pouvoir +aisément +systèmes +quelque +soit +leur +environnement +d'exécution +stockage +visualisation +sont +intentionnellement +laissés +d'autres +comprendre +sortantes +logiciel +d’aujourd’hui +souhaitez +jetez +oeil +valeurs +principaux +suivants +spécification +communautaires +brève +êtes +standardisée +autres diff --git a/content/fr/docs/what-is-opentelemetry.md b/content/fr/docs/what-is-opentelemetry.md new file mode 100644 index 000000000000..e6e7ea1bcfe3 --- /dev/null +++ b/content/fr/docs/what-is-opentelemetry.md @@ -0,0 +1,133 @@ +--- +title: Qu'est-ce qu'OpenTelemetry ? +description: + Une brève explication de ce qu'est OpenTelemetry, et de ce qu'il n'est pas. +weight: 150 +default_lang_commit: 71833a5f8b84110dadf1e98604b87a900724ac33 +--- + +OpenTelemetry, c'est : + +- Un framework + d'[observabilité](/docs/concepts/observability-primer/#what-is-observability) + et des outils conçus pour créer et gérer des données de télémétrie telles que + des [traces](/docs/concepts/signals/traces/), des + [metriques](/docs/concepts/signals/metrics/), et des + [logs](/docs/concepts/signals/logs/) +- Indépendant d'un fournisseur et d'un outil, ce qui signifie qu'il peut être + utilisé avec une grande variété de backends d'observabilité, y compris des + outils open source tels que [Jaeger](https://www.jaegertracing.io/) et + [Prometheus](https://prometheus.io/), ainsi que des outils commerciaux +- Pas un backend d'observabilité tel que Jaeger, Prometheus ou d'autres outils + commerciaux +- Axé sur la génération, la collecte, la gestion et l'export de données de + télémétrie. L'un des objectifs principaux d'OpenTelemetry est de pouvoir + aisément instrumenter vos applications ou systèmes, quelque soit leur langage, + infrastructure, ou environnement d'exécution. Le stockage et la visualisation + des données sont intentionnellement laissés à d'autres outils + +## Qu'est-ce que l'observabilité ? + +L'[observabilité](/docs/concepts/observability-primer/#what-is-observability) +est la capacité de comprendre l'état interne d'un système en examinant ses +données sortantes. Dans un contexte logiciel, cela signifie être capable de +comprendre l'état interne d'un système en examinant ses données de télémétrie, +qui incluent les traces, métriques et logs. + +Pour rendre un système observable, il doit être +[instrumenté](/docs/concepts/instrumentation). Cela signifie que le code doit +émettre des [traces](/docs/concepts/signals/traces/), des +[métriques](/docs/concepts/signals/metrics/), et/ou des +[logs](/docs/concepts/signals/logs/). Les données produites doivent être +transmises à un backend d'observabilité. + +## Pourquoi OpenTelemetry ? + +Avec l'essor du cloud computing, des architectures en microservices, et des +exigences commerciales de plus en plus complexes, le besoin +d'[observabilité](/docs/concepts/observability-primer/#what-is-observability) +des logiciels et de l'infrastructure est plus grand que jamais. + +OpenTelemetry répond au besoin d'observabilité tout en suivant deux principes +clés : + +1. Vous êtes propriétaire des données que vous générez. Il n'y a pas de + dépendance vis-à-vis d'un fournisseur +2. Vous n'avez besoin d'apprendre qu'un seul ensemble d'APIs et de conventions + +Ces deux principes combinés offrent aux équipes et aux organisations la +flexibilité dont elles ont besoin dans le monde informatique moderne +d’aujourd’hui. + +Si vous souhaitez en savoir plus, jetez un oeil à la +[mission, la vision et les valeurs](/community/mission/) d'OpenTelemetry. + +## Composants principaux d'OpenTelemetry + +OpenTelemetry se compose des principaux composants suivants : + +- Une [spécification](/docs/specs/otel) pour tous les composants +- Un [protocole](/docs/specs/otlp/) standardisé définissant le format des + données de télémétrie +- Des [conventions sémantiques](/docs/specs/semconv/) définissant une + nomenclature standardisée pour décrire les données de télémétrie +- Des APIs décrivant comment générer des données de télémétrie +- Des [SDKs par langage](/docs/languages) qui implémentent les spécifications, + les APIs et l'export des données de télémétrie +- Un [écosystème de bibliothèques](/ecosystem/registry) qui instrumentent des + bibliothèques et frameworks +- Des composants d'instrumentation automatique qui génèrent des données de + télémétrie sans requérir de modifications de code +- Le [Collector OpenTelemetry](/docs/collector), un proxy qui reçoit, modifie et + exporte les données de télémétrie +- Divers autres outils, tels que + l'[Opérateur Kubernetes pour OpenTelemetry](/docs/kubernetes/operator/), les + [Helm Charts pour OpenTelemetry](/docs/kubernetes/helm/) et des + [ressources communautaires pour les FaaS](/docs/faas/) + +OpenTelemetry est utilisé par une grande variété de +[bibliothèques, services et applications](/ecosystem/integrations/) qui +intègrent OpenTelemetry afin de fournir de l'observabilité par défaut. + +OpenTelemetry est pris en charge par de nombreux +[fournisseurs](/ecosystem/vendors/), dont beaucoup fournissent un support +commercial à OpenTelemetry et contribuent au projet directement. + +## Extensibilité + +OpenTelemetry est conçu pour être extensible. Quelques exemples de la façon dont +il peut être étendu incluent : + +- Ajouter un receveur au Collecteur OpenTelemetry afin de prendre en charge les + données de télémétrie venant d'une source de données personnalisée +- Charger des bibliothèques d'instrumentation personnalisées dans un SDK +- Créer une [distribution](/docs/concepts/distributions/) d'un SDK, ou du + collecteur adapté à une utilisation spécifique +- Créer un nouvel exportateur pour un backend personnalisé qui ne prend pas + encore en charge le protocole OpenTelemetry (OTLP) +- Créer un propagateur personnalisé pour un format de propagation de contexte + non standard + +Bien que la plupart des utilisateurs n’aient pas besoin d’étendre OpenTelemetry, +le projet est conçu pour rendre cela possible presque à tous les niveaux. + +## Histoire + +OpenTelemetry est un projet de la +[Cloud Native Computing Foundation (CNCF)](https://www.cncf.io) qui trouve son +origine dans la fusion de deux projets antérieurs, +[OpenTracing](https://opentracing.io) et [OpenCensus](https://opencensus.io). +Ces deux projets ont été créés pour résoudre le même problème : l'absence d'une +norme décrivant la manière d'instrumenter du code et de transmettre des données +de télémétrie à un backend d'observabilité. Aucun des projets n'étant en mesure +de résoudre ce problème de manière indépendante, ils ont fusionné pour former +OpenTelemetry et combiner leurs forces tout en offrant une solution unique. + +Si vous utilisez actuellement OpenTracing ou OpenCensus, vous pouvez découvrir +comment migrer vers OpenTelemetry dans le +[guide de migration](/docs/migration/). + +## Et ensuite ? + +- [Pour commencer](/docs/getting-started/) — Lancez-vous directement ! +- Découvrez les [concepts d'OpenTelemetry](/docs/concepts/) From e6eef276715e2121e73bb6e8e888bdbb3b52fe9a Mon Sep 17 00:00:00 2001 From: Damien Mathieu <42@dmathieu.com> Date: Wed, 16 Oct 2024 14:17:05 +0200 Subject: [PATCH 07/19] Remove otelmacaron from registry (#5418) --- data/registry/instrumentation-go-otelmacaron.yml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 data/registry/instrumentation-go-otelmacaron.yml diff --git a/data/registry/instrumentation-go-otelmacaron.yml b/data/registry/instrumentation-go-otelmacaron.yml deleted file mode 100644 index 731c52ae1dbd..000000000000 --- a/data/registry/instrumentation-go-otelmacaron.yml +++ /dev/null @@ -1,16 +0,0 @@ -# cSpell:ignore otelmacaron macaron gopkg -title: Macaron Instrumentation -registryType: instrumentation -language: go -tags: - - macaron - - instrumentation - - go -license: Apache 2.0 -description: Package otelmacaron instruments gopkg.in/macaron.v1. -authors: - - name: OpenTelemetry Authors -urls: - repo: https://go.opentelemetry.io/contrib/instrumentation/gopkg.in/macaron.v1/otelmacaron -createdAt: 2023-12-05 -isFirstParty: false From 2394fa1f1c693e547093e46e83a6819d3c26e9d5 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:05:49 -0500 Subject: [PATCH 08/19] Refactor java instrumentation (#5276) Co-authored-by: Patrice Chalin --- .gitmodules | 2 +- .htmltest.yml | 2 + content-modules/opentelemetry-java-examples | 2 +- content/en/blog/2023/spring-native/index.md | 10 +- content/en/docs/collector/deployment/agent.md | 2 +- .../concepts/instrumentation/libraries.md | 6 +- .../en/docs/languages/java/api-components.md | 1688 +++++++++++++++++ content/en/docs/languages/java/api.md | 4 +- .../en/docs/languages/java/configuration.md | 4 +- .../en/docs/languages/java/instrumentation.md | 1368 ++----------- content/en/docs/languages/java/libraries.md | 187 -- content/en/docs/languages/java/sdk.md | 24 +- layouts/partials/docs/native-libraries.md | 31 + .../docs/languages/libraries-intro.md | 22 +- .../docs/languages/native-libraries.md | 1 + static/refcache.json | 136 ++ 16 files changed, 2090 insertions(+), 1399 deletions(-) create mode 100644 content/en/docs/languages/java/api-components.md delete mode 100644 content/en/docs/languages/java/libraries.md create mode 100644 layouts/partials/docs/native-libraries.md create mode 100644 layouts/shortcodes/docs/languages/native-libraries.md diff --git a/.gitmodules b/.gitmodules index b3e0735ae018..ec8382827470 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,4 +31,4 @@ [submodule "content-modules/opentelemetry-java-examples"] path = content-modules/opentelemetry-java-examples url = https://github.com/open-telemetry/opentelemetry-java-examples.git - javaexamples-pin = 8fe9a11 + javaexamples-pin = 0f736ec diff --git a/.htmltest.yml b/.htmltest.yml index 9ad637f30f5d..58774c8382e5 100644 --- a/.htmltest.yml +++ b/.htmltest.yml @@ -10,6 +10,8 @@ IgnoreDirs: - ^blog/(\d+/)?page/\d+ # TODO drop after https://github.com/open-telemetry/opentelemetry.io/issues/5267 is fixed: - zh/docs/contributing/pr-checks + # TODO drop after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed: + - (ja|pt)/docs/concepts/instrumentation/libraries/ IgnoreInternalURLs: # list of paths IgnoreURLs: # list of regexs of paths or URLs to be ignored - ^/api$ diff --git a/content-modules/opentelemetry-java-examples b/content-modules/opentelemetry-java-examples index 8fe9a11a33af..0f736eca6a4b 160000 --- a/content-modules/opentelemetry-java-examples +++ b/content-modules/opentelemetry-java-examples @@ -1 +1 @@ -Subproject commit 8fe9a11a33affcc4942f2df6668cd6ce787cde3f +Subproject commit 0f736eca6a4b6865fb62b00033a53369e69440f7 diff --git a/content/en/blog/2023/spring-native/index.md b/content/en/blog/2023/spring-native/index.md index acb1127a0601..5c4aaab586fe 100644 --- a/content/en/blog/2023/spring-native/index.md +++ b/content/en/blog/2023/spring-native/index.md @@ -37,11 +37,11 @@ Boot 3) out of the box: ``` To get even more visibility, the Starter can be combined with -[instrumentation libraries](/docs/languages/java/libraries/). For this purpose, -the OpenTelemetry Java contributors have improved the JDBC (database) libraries -and logging instrumentation libraries. For example, for the Logback logging -library, they have added GraalVM configuration to make the library work in -native mode[^1]. +[instrumentation libraries](/docs/languages/java/instrumentation/). For this +purpose, the OpenTelemetry Java contributors have improved the JDBC (database) +libraries and logging instrumentation libraries. For example, for the Logback +logging library, they have added GraalVM configuration to make the library work +in native mode[^1]. Furthermore, they have worked to reduce the configuration to set up the logging and database instrumentation with the Starter. For example, if your application diff --git a/content/en/docs/collector/deployment/agent.md b/content/en/docs/collector/deployment/agent.md index 2a17343c3b7b..eff8d8df82ef 100644 --- a/content/en/docs/collector/deployment/agent.md +++ b/content/en/docs/collector/deployment/agent.md @@ -129,7 +129,7 @@ Cons: [instrumentation]: /docs/languages/ [otlp]: /docs/specs/otel/protocol/ [collector]: /docs/collector/ -[instrument-java-metrics]: /docs/languages/java/instrumentation/#metrics +[instrument-java-metrics]: /docs/languages/java/api-components/#meterprovider [otlp-exporter]: /docs/specs/otel/protocol/exporter/ [java-otlp-example]: https://github.com/open-telemetry/opentelemetry-java-docs/tree/main/otlp diff --git a/content/en/docs/concepts/instrumentation/libraries.md b/content/en/docs/concepts/instrumentation/libraries.md index 9d240f97b2ad..3501730b343c 100644 --- a/content/en/docs/concepts/instrumentation/libraries.md +++ b/content/en/docs/concepts/instrumentation/libraries.md @@ -265,7 +265,7 @@ After you create a span, pass new trace context to the application code (callback or handler), by making the span active; if possible, do this explicitly. The following Java example shows how to add trace context and activate a span. See the -[Context extraction in Java](/docs/languages/java/instrumentation/#context-propagation), +[Context extraction in Java](/docs/languages/java/api-components/#contextpropagators), for more examples. ```java @@ -289,9 +289,7 @@ try (Scope unused = span.makeCurrent()) { ``` In the case of a messaging system, you might receive more than one message at -once. Received messages become -[links](/docs/languages/java/instrumentation/#create-spans-with-links) on the -span you create. Refer to +once. Received messages become links on the span you create. Refer to [messaging conventions](/docs/specs/semconv/messaging/messaging-spans/) for details. diff --git a/content/en/docs/languages/java/api-components.md b/content/en/docs/languages/java/api-components.md new file mode 100644 index 000000000000..c5df547cdf7a --- /dev/null +++ b/content/en/docs/languages/java/api-components.md @@ -0,0 +1,1688 @@ +--- +title: Record Telemetry with API +weight: 11 +logBridgeWarning: > + While the `LoggerProvider` / `Logger` APIs are structurally similar to the + equivalent trace and metric APIs, they serve a different use case. As of now, + `LoggerProvider` / `Logger` and associated classes represent the [Log Bridge + API](/docs/specs/otel/logs/bridge-api/), which exists to write log appenders + to bridge logs recorded through other log APIs / frameworks into + OpenTelemetry. They are not intended for end user use as a replacement for + Log4j / SLF4J / Logback / etc. +cSpell:ignore: Dotel kotlint Logback updowncounter +--- + + + + +The API is a set of classes and interfaces for recording telemetry across key +observability signals. The [SDK](../sdk/) is the built-in reference +implementation of the API, [configured](../configuration/) to process and export +telemetry. This page is a conceptual overview of the API, including +descriptions, links to relevant Javadocs, artifact coordinates, and sample API +usage. + +The API consists of the following top-level components: + +- [Context](#context-api): A standalone API for propagating context throughout + an application and across application boundaries, including trace context and + baggage. +- [TracerProvider](#tracerprovider): The API entry point for traces. +- [MeterProvider](#meterprovider): The API entry point for metrics. +- [LoggerProvider](#loggerprovider): The API entry point for logs. +- [OpenTelemetry](#opentelemetry): A holder for top-level API components (i.e. + `TracerProvider`, `MeterProvider`, `LoggerProvider`, `ContextPropagators`) + which is convenient to pass to instrumentation. + +The API is designed to support multiple implementations. Two implementations are +provided by OpenTelemetry: + +- [SDK](../sdk/) reference implementation. This is the right choice for most + users. +- [Noop](#noop-implementation) implementation. A minimalist, zero-dependency + implementation for instrumentations to use by default when the user doesn't + install an instance. + +The API is designed to be taken as a direct dependency by libraries, frameworks, +and application owners. It comes with +[strong backwards compatibility guarantees](https://github.com/open-telemetry/opentelemetry-java/blob/main/VERSIONING.md#compatibility-requirements), +zero transitive dependencies, and +[supports Java 8+](https://github.com/open-telemetry/opentelemetry-java/blob/main/VERSIONING.md#language-version-compatibility). +Libraries and frameworks should depend only on the API and only call methods +from the API, and instruct applications / end users to add a dependency on the +SDK and install a configured instance. + +## API Components + +The following sections describe the OpenTelemetry API. Each component section +includes: + +- A brief description, including a link to the Javadoc type reference. +- Links to relevant resources to understand the API methods and arguments. +- A simple exploration of API usage. + +## Context API + +The `io.opentelemetry:opentelemetry-api-context:{{% param vers.otel %}}` +artifact contains standalone APIs (i.e. packaged separately from +[OpenTelemetry API](#opentelemetry-api)) for propagating context throughout an +application and across application boundaries. + +It consists of: + +- [Context](#context): An immutable bundle of key value pairs which is + implicitly or explicitly propagated through an application. +- [ContextStorage](#contextstorage): A mechanism for storing and retrieving the + current context, defaulting to thread local. +- [ContextPropagators](#context): A container of registered propagators for + propagating `Context` across application boundaries. + +The `io.opentelemetry:opentelemetry-extension-kotlint:{{% param vers.otel %}}` +is an extension with tools for propagating context into coroutines. + +### Context + +[Context](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/Context.html) +is an immutable bundle of key value pairs, with utilities for implicitly +propagating through an application and across threads. Implicit propagation +means that the context can be accessed without explicitly passing it as an +argument. Context is a recurring concept in the OpenTelemetry API: + +- The current active [Span](#span) is stored in context, and by default a span's + parent is assigned to whatever span is currently in context. +- The measurements recorded to [metric instruments](#meter) accept a context + argument, used to link measurements to spans via + [exemplars](/docs/specs/otel/metrics/data-model/#exemplars) and defaulting to + whatever span is currently in context. +- [LogRecords](#logrecordbuilder) accept a context argument, used to link log + record spans and defaulting to whatever span is currently in context. + +The following code snippet explores `Context` API usage: + + + +```java +package otel; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextKey; +import io.opentelemetry.context.Scope; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class ContextUsage { + public static void contextUsage() throws Exception { + // Define an example context key + ContextKey exampleContextKey = ContextKey.named("example-context-key"); + + // Context doesn't contain the key until we add it + // Context.current() accesses the current context + // output => current context value: null + System.out.println("current context value: " + Context.current().get(exampleContextKey)); + + // Add entry to context + Context context = Context.current().with(exampleContextKey, "value"); + + // The local context var contains the added value + // output => context value: value + System.out.println("context value: " + context.get(exampleContextKey)); + // The current context still doesn't contain the value + // output => current context value: null + System.out.println("current context value: " + Context.current().get(exampleContextKey)); + + // Calling context.makeCurrent() sets Context.current() to the context until the scope is + // closed, upon which Context.current() is restored to the state prior to when + // context.makeCurrent() was called. The resulting Scope implements AutoCloseable and is + // normally used in a try-with-resources block. Failure to call Scope.close() is an error and + // may cause memory leaks or other issues. + try (Scope scope = context.makeCurrent()) { + // The current context now contains the added value + // output => context value: value + System.out.println("context value: " + context.get(exampleContextKey)); + } + + // The local context var still contains the added value + // output => context value: value + System.out.println("context value: " + context.get(exampleContextKey)); + // The current context no longer contains the value + // output => current context value: null + System.out.println("current context value: " + Context.current().get(exampleContextKey)); + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); + + // Context instances can be explicitly passed around application code, but it's more convenient + // to use implicit context, calling Context.makeCurrent() and accessing via Context.current(). + // Context provides a number of utilities for implicit context propagation. These utilities wrap + // utility classes like Scheduler, ExecutorService, ScheduledExecutorService, Runnable, + // Callable, Consumer, Supplier, Function, etc and modify their behavior to call + // Context.makeCurrent() before running. + context.wrap(ContextUsage::callable).call(); + context.wrap(ContextUsage::runnable).run(); + context.wrap(executorService).submit(ContextUsage::runnable); + context.wrap(scheduledExecutorService).schedule(ContextUsage::runnable, 1, TimeUnit.SECONDS); + context.wrapConsumer(ContextUsage::consumer).accept(new Object()); + context.wrapConsumer(ContextUsage::biConsumer).accept(new Object(), new Object()); + context.wrapFunction(ContextUsage::function).apply(new Object()); + context.wrapSupplier(ContextUsage::supplier).get(); + } + + /** Example {@link java.util.concurrent.Callable}. */ + private static Object callable() { + return new Object(); + } + + /** Example {@link Runnable}. */ + private static void runnable() {} + + /** Example {@link java.util.function.Consumer}. */ + private static void consumer(Object object) {} + + /** Example {@link java.util.function.BiConsumer}. */ + private static void biConsumer(Object object1, Object object2) {} + + /** Example {@link java.util.function.Function}. */ + private static Object function(Object object) { + return object; + } + + /** Example {@link java.util.function.Supplier}. */ + private static Object supplier() { + return new Object(); + } +} +``` + + +### ContextStorage + +[ContextStorage](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/ContextStorage.html) +is a mechanism for storing and retrieving the current `Context`. + +The default `ContextStorage` implementation stores `Context` in thread local. + +### ContextPropagators + +[ContextPropagators](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/propagation/ContextPropagators.html) +is a container of registered propagators for propagating `Context` across +application boundaries. Context is injected into a carrier when leaving an +application (i.e. an outbound HTTP request), and extracted from a carrier when +entering an application (i.e. serving an HTTP request). + +See [SDK TextMapPropagators](../sdk/#textmappropagator) for propagator +implementations. + +The following code snippet explores `ContextPropagators` API for injection: + + + +```java +package otel; + +import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.context.propagation.TextMapSetter; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public class InjectContextUsage { + private static final TextMapSetter TEXT_MAP_SETTER = new HttpRequestSetter(); + + public static void injectContextUsage() throws Exception { + // Create a ContextPropagators instance which propagates w3c trace context and w3c baggage + ContextPropagators propagators = + ContextPropagators.create( + TextMapPropagator.composite( + W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance())); + + // Create an HttpRequest builder + HttpClient httpClient = HttpClient.newBuilder().build(); + HttpRequest.Builder requestBuilder = + HttpRequest.newBuilder().uri(new URI("http://127.0.0.1:8080/resource")).GET(); + + // Given a ContextPropagators instance, inject the current context into the HTTP request carrier + propagators.getTextMapPropagator().inject(Context.current(), requestBuilder, TEXT_MAP_SETTER); + + // Send the request with the injected context + httpClient.send(requestBuilder.build(), HttpResponse.BodyHandlers.discarding()); + } + + /** {@link TextMapSetter} with a {@link HttpRequest.Builder} carrier. */ + private static class HttpRequestSetter implements TextMapSetter { + @Override + public void set(HttpRequest.Builder carrier, String key, String value) { + if (carrier == null) { + return; + } + carrier.setHeader(key, value); + } + } +} +``` + + +The following code snippet explores `ContextPropagators` API for extraction: + + + +```java +package otel; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.context.propagation.TextMapSetter; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class ExtractContextUsage { + private static final TextMapGetter TEXT_MAP_GETTER = new HttpRequestGetter(); + + public static void extractContextUsage() throws Exception { + // Create a ContextPropagators instance which propagates w3c trace context and w3c baggage + ContextPropagators propagators = + ContextPropagators.create( + TextMapPropagator.composite( + W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance())); + + // Create a server, which uses the propagators to extract context from requests + HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); + server.createContext("/path", new Handler(propagators)); + server.setExecutor(null); + server.start(); + } + + private static class Handler implements HttpHandler { + private final ContextPropagators contextPropagators; + + private Handler(ContextPropagators contextPropagators) { + this.contextPropagators = contextPropagators; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + // Extract the context from the request and make the context current + Context extractedContext = + contextPropagators + .getTextMapPropagator() + .extract(Context.current(), exchange, TEXT_MAP_GETTER); + try (Scope scope = extractedContext.makeCurrent()) { + // Do work with the extracted context + } finally { + String response = "success"; + exchange.sendResponseHeaders(200, response.length()); + OutputStream os = exchange.getResponseBody(); + os.write(response.getBytes(StandardCharsets.UTF_8)); + os.close(); + } + } + } + + /** {@link TextMapSetter} with a {@link HttpExchange} carrier. */ + private static class HttpRequestGetter implements TextMapGetter { + @Override + public Iterable keys(HttpExchange carrier) { + return carrier.getRequestHeaders().keySet(); + } + + @Override + public String get(HttpExchange carrier, String key) { + if (carrier == null) { + return null; + } + List headers = carrier.getRequestHeaders().get(key); + if (headers == null || headers.isEmpty()) { + return null; + } + return headers.get(0); + } + } +} +``` + + +## OpenTelemetry API + +The `io.opentelemetry:opentelemetry-api:{{% param vers.otel %}}` artifact +contains the OpenTelemetry API, including traces, metrics, logs, noop +implementation, baggage, key `TextMapPropagator` implementations, and a +dependency on the [context API](#context-api). + +### Providers and Scopes + +Providers and scopes are recurring concepts in the OpenTelemetry API. A scope is +a logical unit within the application which telemetry is associated with. A +provider provides components for recording telemetry relative to a particular +scope: + +- [TracerProvider](#tracerprovider) provides scoped [Tracers](#tracer) for + recording spans. +- [MeterProvider](#meterprovider) provides scoped [Meters](#meter) for recording + metrics. +- [LoggerProvider](#loggerprovider) provides scoped [Loggers](#logger) for + recording logs. + +{{% alert %}} {{% param logBridgeWarning %}} {{% /alert %}} + +A scope is identified by the triplet (name, version, schemaUrl). Care must be +taken to ensure the scope identity is unique. A typical approach is to set the +scope name to the package name or fully qualified class name, and to set the +scope version to the library version. If emitting telemetry for multiple signals +(i.e. metrics and traces), the same scope should be used. See +[instrumentation scope](/docs/concepts/instrumentation-scope/) for details. + +The following code snippet explores provider and scope API usage: + + + +```java +package otel; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.api.logs.LoggerProvider; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.MeterProvider; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.api.trace.TracerProvider; + +public class ProvidersAndScopes { + + private static final String SCOPE_NAME = "fully.qualified.name"; + private static final String SCOPE_VERSION = "1.0.0"; + private static final String SCOPE_SCHEMA_URL = "https://example"; + + public static void providersUsage(OpenTelemetry openTelemetry) { + // Access providers from an OpenTelemetry instance + TracerProvider tracerProvider = openTelemetry.getTracerProvider(); + MeterProvider meterProvider = openTelemetry.getMeterProvider(); + // NOTE: LoggerProvider is a special case and should only be used to bridge logs from other + // logging APIs / frameworks into OpenTelemetry. + LoggerProvider loggerProvider = openTelemetry.getLogsBridge(); + + // Access tracer, meter, logger from providers to record telemetry for a particular scope + Tracer tracer = + tracerProvider + .tracerBuilder(SCOPE_NAME) + .setInstrumentationVersion(SCOPE_VERSION) + .setSchemaUrl(SCOPE_SCHEMA_URL) + .build(); + Meter meter = + meterProvider + .meterBuilder(SCOPE_NAME) + .setInstrumentationVersion(SCOPE_VERSION) + .setSchemaUrl(SCOPE_SCHEMA_URL) + .build(); + Logger logger = + loggerProvider + .loggerBuilder(SCOPE_NAME) + .setInstrumentationVersion(SCOPE_VERSION) + .setSchemaUrl(SCOPE_SCHEMA_URL) + .build(); + + // ...optionally, shorthand versions are available if scope version and schemaUrl aren't + // available + tracer = tracerProvider.get(SCOPE_NAME); + meter = meterProvider.get(SCOPE_NAME); + logger = loggerProvider.get(SCOPE_NAME); + } +} +``` + + +### Attributes + +[Attributes](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/common/Attributes.html) +is a bundle of key value pairs representing the +[standard attribute definition](/docs/specs/otel/common/#standard-attribute). +`Attributes` are a recurring concept in the OpenTelemetry API: + +- [Spans](#span), span events, and span links have attributes. +- The measurements recorded to [metric instruments](#meter) have attributes. +- [LogRecords](#logrecordbuilder) have attributes. + +See [semantic attributes](#semantic-attributes) for attribute constants +generated from the semantic conventions. + +See [attribute naming](/docs/specs/semconv/general/attribute-naming/) for +guidance on attribute naming. + +The following code snippet explores `Attributes` API usage: + + + +```java +package otel; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; +import java.util.Map; + +public class AttributesUsage { + // Establish static constant for attribute keys and reuse to avoid allocations + private static final AttributeKey SHOP_ID = AttributeKey.stringKey("com.acme.shop.id"); + private static final AttributeKey SHOP_NAME = + AttributeKey.stringKey("com.acme.shop.name"); + private static final AttributeKey CUSTOMER_ID = + AttributeKey.longKey("com.acme.customer.id"); + private static final AttributeKey CUSTOMER_NAME = + AttributeKey.stringKey("com.acme.customer.name"); + + public static void attributesUsage() { + // Use a varargs initializer and pre-allocated attribute keys. This is the most efficient way to + // create attributes. + Attributes attributes = + Attributes.of( + SHOP_ID, + "abc123", + SHOP_NAME, + "opentelemetry-demo", + CUSTOMER_ID, + 123L, + CUSTOMER_NAME, + "Jack"); + + // ...or use a builder. + attributes = + Attributes.builder() + .put(SHOP_ID, "abc123") + .put(SHOP_NAME, "opentelemetry-demo") + .put(CUSTOMER_ID, 123) + .put(CUSTOMER_NAME, "Jack") + // Optionally initialize attribute keys on the fly + .put(AttributeKey.stringKey("com.acme.string-key"), "value") + .put(AttributeKey.booleanKey("com.acme.bool-key"), true) + .put(AttributeKey.longKey("com.acme.long-key"), 1L) + .put(AttributeKey.doubleKey("com.acme.double-key"), 1.1) + .put(AttributeKey.stringArrayKey("com.acme.string-array-key"), "value1", "value2") + .put(AttributeKey.booleanArrayKey("come.acme.bool-array-key"), true, false) + .put(AttributeKey.longArrayKey("come.acme.long-array-key"), 1L, 2L) + .put(AttributeKey.doubleArrayKey("come.acme.double-array-key"), 1.1, 2.2) + // Optionally omit initializing AttributeKey + .put("com.acme.string-key", "value") + .put("com.acme.bool-key", true) + .put("come.acme.long-key", 1L) + .put("come.acme.double-key", 1.1) + .put("come.acme.string-array-key", "value1", "value2") + .put("come.acme.bool-array-key", true, false) + .put("come.acme.long-array-key", 1L, 2L) + .put("come.acme.double-array-key", 1.1, 2.2) + .build(); + + // Attributes has a variety of methods for manipulating and reading data. + // Read an attribute key: + String shopIdValue = attributes.get(SHOP_ID); + // Inspect size: + int size = attributes.size(); + boolean isEmpty = attributes.isEmpty(); + // Convert to a map representation: + Map, Object> map = attributes.asMap(); + // Iterate through entries, printing each to the template: (): \n + attributes.forEach( + (attributeKey, value) -> + System.out.printf( + "%s (%s): %s%n", attributeKey.getKey(), attributeKey.getType(), value)); + // Convert to a builder, remove the com.acme.customer.id and any entry whose key starts with + // com.acme.shop, and build a new instance: + AttributesBuilder builder = attributes.toBuilder(); + builder.remove(CUSTOMER_ID); + builder.removeIf(attributeKey -> attributeKey.getKey().startsWith("com.acme.shop")); + Attributes trimmedAttributes = builder.build(); + } +} +``` + + +### OpenTelemetry + +[OpenTelemetry](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/OpenTelemetry.html) +is a holder for top-level API components which is convenient to pass to +instrumentation. + +`OpenTelemetry` consists of: + +- [TracerProvider](#tracerprovider): The API entry point for traces. +- [MeterProvider](#meterprovider): The API entry point for metrics. +- [LoggerProvider](#loggerprovider): The API entry point for logs. +- [ContextPropagators](#contextpropagators): The API entry point for context + propagation. + +The following code snippet explores `OpenTelemetry` API usage: + + + +```java +package otel; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.logs.LoggerProvider; +import io.opentelemetry.api.metrics.MeterProvider; +import io.opentelemetry.api.trace.TracerProvider; +import io.opentelemetry.context.propagation.ContextPropagators; + +public class OpenTelemetryUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void openTelemetryUsage(OpenTelemetry openTelemetry) { + // Access TracerProvider, MeterProvider, LoggerProvider, ContextPropagators + TracerProvider tracerProvider = openTelemetry.getTracerProvider(); + MeterProvider meterProvider = openTelemetry.getMeterProvider(); + LoggerProvider loggerProvider = openTelemetry.getLogsBridge(); + ContextPropagators propagators = openTelemetry.getPropagators(); + } +} +``` + + +### GlobalOpenTelemetry + +[GlobalOpenTelemetry](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/GlobalOpenTelemetry.html) +holds a global singleton [OpenTelemetry](#opentelemetry) instance. + +Instrumentation should avoid using `GlobalOpenTelemetry`. Instead, accept +`OpenTelemetry` as an initialization argument and default to the +[Noop implementation](#noop-implementation) if not set. There is an exception to +this rule: the `OpenTelemetry` instance installed by the +[Java agent](/docs/zero-code/java/agent/) is available via +`GlobalOpenTelemetry`. Users with additional manual instrumentation are +encouraged to access it via `GlobalOpenTelemetry.get()`. + +`GlobalOpenTelemetry.get()` is guaranteed to always return the same result. If +`GlobalOpenTelemetry.get()` is called before `GlobalOpenTelemetry.set(..)`, +`GlobalOpenTelemetry` is set to the noop implementation and future calls to +`GlobalOpenTelemetry.set(..)` throw an exception. Therefore, it's critical to +call `GlobalOpenTelemetry.set(..)` as early in the application lifecycle as +possible, and before `GlobalOpenTelemetry.get()` is called by any +instrumentation. This guarantee surfaces initialization ordering issues: calling +`GlobalOpenTelemetry.set()` too late (i.e. after instrumentation has called +`GlobalOpenTelemetry.get()`) triggers an exception rather than silently failing. + +If [autoconfigure](../configuration/#zero-code-sdk-autoconfigure) is present, +`GlobalOpenTelemetry` can be automatically initialized by setting +`-Dotel.java.global-autoconfigure.enabled=true` (or via env var +`export OTEL_JAVA_GLOBAL_AUTOCONFIGURE_ENABLED=true`). When enabled, the first +call to `GlobalOpenTelemetry.get()` triggers autoconfiguration and calls +`GlobalOpenTelemetry.set(..)` with the resulting `OpenTelemetry` instance. + +The following code snippet explores `GlobalOpenTelemetry` API context +propagation: + + + +```java +package otel; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; + +public class GlobalOpenTelemetryUsage { + + public static void openTelemetryUsage(OpenTelemetry openTelemetry) { + // Set the GlobalOpenTelemetry instance as early in the application lifecycle as possible + // Set must only be called once. Calling multiple times raises an exception. + GlobalOpenTelemetry.set(openTelemetry); + + // Get the GlobalOpenTelemetry instance. + openTelemetry = GlobalOpenTelemetry.get(); + } +} +``` + + +### TracerProvider + +[TracerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/TracerProvider.html) +is the API entry point for traces and provides [Tracers](#tracer). See +[providers and scopes](#providers-and-scopes) for information on providers and +scopes. + +#### Tracer + +[Tracer](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/Tracer.html) +is used to [record spans](#span) for an instrumentation scope. See +[providers and scopes](#providers-and-scopes) for information on providers and +scopes. + +#### Span + +[SpanBuilder](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/SpanBuilder.html) +and +[Span](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/Span.html) +are used to construct and record data to spans. + +`SpanBuilder` is used to add data to a span before starting it by calling +`Span startSpan()`. Data can be added / updated after starting by calling +various `Span` update methods. The data provided to `SpanBuilder` before +starting is provided as an input to [Samplers](../sdk/#sampler). + +The following code snippet explores `SpanBuilder` / `Span` API usage: + + + +```java +package otel; + +import static io.opentelemetry.context.Context.current; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import java.util.Arrays; + +public class SpanUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void spanUsage(Tracer tracer) { + // Get a span builder by providing the span name + Span span = + tracer + .spanBuilder("span name") + // Set span kind + .setSpanKind(SpanKind.INTERNAL) + // Set attributes + .setAttribute(AttributeKey.stringKey("com.acme.string-key"), "value") + .setAttribute(AttributeKey.booleanKey("com.acme.bool-key"), true) + .setAttribute(AttributeKey.longKey("com.acme.long-key"), 1L) + .setAttribute(AttributeKey.doubleKey("com.acme.double-key"), 1.1) + .setAttribute( + AttributeKey.stringArrayKey("com.acme.string-array-key"), + Arrays.asList("value1", "value2")) + .setAttribute( + AttributeKey.booleanArrayKey("come.acme.bool-array-key"), + Arrays.asList(true, false)) + .setAttribute( + AttributeKey.longArrayKey("come.acme.long-array-key"), Arrays.asList(1L, 2L)) + .setAttribute( + AttributeKey.doubleArrayKey("come.acme.double-array-key"), Arrays.asList(1.1, 2.2)) + // Optionally omit initializing AttributeKey + .setAttribute("com.acme.string-key", "value") + .setAttribute("com.acme.bool-key", true) + .setAttribute("come.acme.long-key", 1L) + .setAttribute("come.acme.double-key", 1.1) + .setAllAttributes(WIDGET_RED_CIRCLE) + // Uncomment to optionally explicitly set the parent span context. If omitted, the + // span's parent will be set using Context.current(). + // .setParent(parentContext) + // Uncomment to optionally add links. + // .addLink(linkContext, linkAttributes) + // Start the span + .startSpan(); + + // Check if span is recording before computing additional data + if (span.isRecording()) { + // Update the span name with information not available when starting + span.updateName("new span name"); + + // Add additional attributes not available when starting + span.setAttribute("com.acme.string-key2", "value"); + + // Add additional span links not available when starting + span.addLink(exampleLinkContext()); + // optionally include attributes on the link + span.addLink(exampleLinkContext(), WIDGET_RED_CIRCLE); + + // Add span events + span.addEvent("my-event"); + // optionally include attributes on the event + span.addEvent("my-event", WIDGET_RED_CIRCLE); + + // Record exception, syntactic sugar for a span event with a specific shape + span.recordException(new RuntimeException("error")); + + // Set the span status + span.setStatus(StatusCode.OK, "status description"); + } + + // Finally, end the span + span.end(); + } + + /** Return a dummy link context. */ + private static SpanContext exampleLinkContext() { + return Span.fromContext(current()).getSpanContext(); + } +} +``` + + +Span parenting is an important aspect of tracing. Each span has an optional +parent. By collecting all the spans in a trace and following each span's parent, +we can construct a hierarchy. The span APIs are built on top of +[context](#context), which allows span context to be implicitly passed around an +application and across threads. When a span is created, its parent is set to the +whatever span is present in `Context.current()` unless there is no span or the +context is explicitly overridden. + +Most of the context API usage guidance applies to spans. Span context is +propagated across application boundaries with the +[W3CTraceContextPropagator](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/propagation/W3CTraceContextPropagator.html) +and other [TextMapPropagators](../sdk/#textmappropagator). + +The following code snippet explores `Span` API context propagation: + + + +```java +package otel; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; + +public class SpanAndContextUsage { + private final Tracer tracer; + + SpanAndContextUsage(Tracer tracer) { + this.tracer = tracer; + } + + public void nestedSpanUsage() { + // Start a span. Since we don't call makeCurrent(), we must explicitly call setParent on + // children. Wrap code in try / finally to ensure we end the span. + Span span = tracer.spanBuilder("span").startSpan(); + try { + // Start a child span, explicitly setting the parent. + Span childSpan = + tracer + .spanBuilder("span child") + // Explicitly set parent. + .setParent(span.storeInContext(Context.current())) + .startSpan(); + // Call makeCurrent(), adding childSpan to Context.current(). Spans created inside the scope + // will have their parent set to childSpan. + try (Scope childSpanScope = childSpan.makeCurrent()) { + // Call another method which creates a span. The span's parent will be childSpan since it is + // started in the childSpan scope. + doWork(); + } finally { + childSpan.end(); + } + } finally { + span.end(); + } + } + + private int doWork() { + Span doWorkSpan = tracer.spanBuilder("doWork").startSpan(); + try (Scope scope = doWorkSpan.makeCurrent()) { + int result = 0; + for (int i = 0; i < 10; i++) { + result += i; + } + return result; + } finally { + doWorkSpan.end(); + } + } +} +``` + + +### MeterProvider + +[MeterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/MeterProvider.html) +is the API entry point for metrics and provides [Meters](#meter). See +[providers and scopes](#providers-and-scopes) for information on providers and +scopes. + +#### Meter + +[Meter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/Meter.html) +is used to obtain instruments for a particular +[instrumentation scope](#providers-and-scopes). See +[providers and scopes](#providers-and-scopes) for information on providers and +scopes. There are a variety of instruments, each with different semantics and +default behavior in the SDK. It's important to choose the right instrument for +each particular use case: + +| Instrument | Sync or Async | Description | Example | Default SDK Aggregation | +| ------------------------------------------- | ------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Counter](#counter) | sync | Record monotonic (positive) values. | Record user logins | [sum (monotonic=true)](/docs/specs/otel/metrics/sdk/#sum-aggregation) | +| [Async Counter](#async-counter) | async | Observe monotonic sums. | Observe number of classes loaded in the JVM | [sum (monotonic=true)](/docs/specs/otel/metrics/sdk/#sum-aggregation) | +| [UpDownCounter](#updowncounter) | sync | Record non-monotonic (positive and negative) values. | Record when items are added to and removed from a queue | [sum (monotonic=false)](/docs/specs/otel/metrics/sdk/#sum-aggregation) | +| [Async UpDownCounter](#async-updowncounter) | async | Observe non-monotonic (positive and negative) sums. | Observe JVM memory pool usage | [sum (monotonic=false)](/docs/specs/otel/metrics/sdk/#sum-aggregation) | +| [Histogram](#histogram) | sync | Record monotonic (positive) values where the distribution is important. | Record duration of HTTP requests processed by server | [ExplicitBucketHistogram](/docs/specs/otel/metrics/sdk/#explicit-bucket-histogram-aggregation) | +| [Gauge](#gauge) | sync | Record the latest value where spatial re-aggregation does not make sense **[1]**. | Record temperature | [LastValue](/docs/specs/otel/metrics/sdk/#last-value-aggregation) | +| [Async Gauge](#async-gauge) | async | Observe the latest value where spatial re-aggregation does not make sense **[1]**. | Observe CPU utilization | [LastValue](/docs/specs/otel/metrics/sdk/#last-value-aggregation) | + +**[1]**: Spatial re-aggregation is the process of merging attribute streams by +dropping attributes which are not needed. For example, given series with +attributes `{"color": "red", "shape": "square"}`, +`{"color": "blue", "shape": "square"}`, you can perform spatial re-aggregation +by dropping the `color` attribute, and merging the series where the attributes +are equal after dropping `color`. Most aggregations have a useful spatial +aggregation merge function (i.e. sums are summed together), but gauges +aggregated by the `LastValue` aggregation are the exception. For example, +suppose the series mentioned previously are tracking the temperature of widgets. +How do you merge the series when you drop the `color` attribute? There is no +good answer besides flipping a coin and selecting a random value. + +The instrument APIs have share a variety of features: + +- Created using the builder pattern. +- Required instrument name. +- Optional unit and description. +- Record values which are `long` or `double`, which is configured via the + builder. + +See +[metric guidelines](http://localhost:1313/docs/specs/semconv/general/metrics/#general-guidelines) +for details on metric naming and units. + +See +[guidelines for instrumentation library authors](/docs/specs/otel/metrics/supplementary-guidelines/#guidelines-for-instrumentation-library-authors) +for additional guidance on instrument selection. + +#### Counter + +[LongCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongCounter.html) +and +[DoubleCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleCounter.html) +are used to record monotonic (positive) values. + +The following code snippet explores counter API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; +import static otel.Util.customContext; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.LongCounter; +import io.opentelemetry.api.metrics.Meter; + +public class CounterUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void counterUsage(Meter meter) { + // Construct a counter to record measurements that are always positive (monotonically + // increasing). + LongCounter counter = + meter + .counterBuilder("fully.qualified.counter") + .setDescription("A count of produced widgets") + .setUnit("{widget}") + // optionally change the type to double + // .ofDoubles() + .build(); + + // Record a measurement with no attributes or context. + // Attributes defaults to Attributes.empty(), context to Context.current(). + counter.add(1L); + + // Record a measurement with attributes, using pre-allocated attributes whenever possible. + counter.add(1L, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + counter.add( + 1L, Attributes.of(WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + + // Record a measurement with attributes, and context. + // Most users will opt to omit the context argument, preferring the default Context.current(). + counter.add(1L, WIDGET_RED_CIRCLE, customContext()); + } +} +``` + + +#### Async Counter + +[ObservableLongCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableLongCounter.htmll) +and +[ObservableDoubleCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableDoubleCounter.html) +are used to observe monotonic (positive) sums. + +The following code snippet explores async counter API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.ObservableLongCounter; +import java.util.concurrent.atomic.AtomicLong; + +public class AsyncCounterUsage { + // Pre-allocate attributes whenever possible + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void asyncCounterUsage(Meter meter) { + AtomicLong widgetCount = new AtomicLong(); + + // Construct an async counter to observe an existing counter in a callback + ObservableLongCounter asyncCounter = + meter + .counterBuilder("fully.qualified.counter") + .setDescription("A count of produced widgets") + .setUnit("{widget}") + // Uncomment to optionally change the type to double + // .ofDoubles() + .buildWithCallback( + // the callback is invoked when a MetricReader reads metrics + observableMeasurement -> { + long currentWidgetCount = widgetCount.get(); + + // Record a measurement with no attributes. + // Attributes defaults to Attributes.empty(). + observableMeasurement.record(currentWidgetCount); + + // Record a measurement with attributes, using pre-allocated attributes whenever + // possible. + observableMeasurement.record(currentWidgetCount, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + observableMeasurement.record( + currentWidgetCount, + Attributes.of( + WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + }); + + // Optionally close the counter to unregister the callback when required + asyncCounter.close(); + } +} +``` + + +#### UpDownCounter + +[LongUpDownCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongUpDownCounter.html) +and +[DoubleUpDownCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleUpDownCounter.html) +are used to record non-monotonic (positive and negative) values. + +The following code snippet explores updowncounter API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; +import static otel.Util.customContext; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.LongUpDownCounter; +import io.opentelemetry.api.metrics.Meter; + +public class UpDownCounterUsage { + + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void usage(Meter meter) { + // Construct an updowncounter to record measurements that go up and down. + LongUpDownCounter upDownCounter = + meter + .upDownCounterBuilder("fully.qualified.updowncounter") + .setDescription("Current length of widget processing queue") + .setUnit("{widget}") + // Uncomment to optionally change the type to double + // .ofDoubles() + .build(); + + // Record a measurement with no attributes or context. + // Attributes defaults to Attributes.empty(), context to Context.current(). + upDownCounter.add(1L); + + // Record a measurement with attributes, using pre-allocated attributes whenever possible. + upDownCounter.add(-1L, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + upDownCounter.add( + -1L, Attributes.of(WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + + // Record a measurement with attributes, and context. + // Most users will opt to omit the context argument, preferring the default Context.current(). + upDownCounter.add(1L, WIDGET_RED_CIRCLE, customContext()); + } +} +``` + + +#### Async UpDownCounter + +[ObservableLongUpDownCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableLongUpDownCounter.html) +and +[ObservableDoubleUpDownCounter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableDoubleUpDownCounter.html) +are used to observe non-monotonic (positive and negative) sums. + +The following code snippet explores async updowncounter API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.ObservableLongUpDownCounter; +import java.util.concurrent.atomic.AtomicLong; + +public class AsyncUpDownCounterUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void asyncUpDownCounterUsage(Meter meter) { + AtomicLong queueLength = new AtomicLong(); + + // Construct an async updowncounter to observe an existing up down counter in a callback + ObservableLongUpDownCounter asyncUpDownCounter = + meter + .upDownCounterBuilder("fully.qualified.updowncounter") + .setDescription("Current length of widget processing queue") + .setUnit("{widget}") + // Uncomment to optionally change the type to double + // .ofDoubles() + .buildWithCallback( + // the callback is invoked when a MetricReader reads metrics + observableMeasurement -> { + long currentWidgetCount = queueLength.get(); + + // Record a measurement with no attributes. + // Attributes defaults to Attributes.empty(). + observableMeasurement.record(currentWidgetCount); + + // Record a measurement with attributes, using pre-allocated attributes whenever + // possible. + observableMeasurement.record(currentWidgetCount, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + observableMeasurement.record( + currentWidgetCount, + Attributes.of( + WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + }); + + // Optionally close the counter to unregister the callback when required + asyncUpDownCounter.close(); + } +} +``` + + +#### Histogram + +[DoubleHistogram](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleHistogram.html) +and +[LongHistogram](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongHistogram.html) +are used to record monotonic (positive) values where the distribution is +important. + +The following code snippet explores histogram API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; +import static otel.Util.customContext; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.Meter; + +public class HistogramUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void histogramUsage(Meter meter) { + // Construct a histogram to record measurements where the distribution is important. + DoubleHistogram histogram = + meter + .histogramBuilder("fully.qualified.histogram") + .setDescription("Length of time to process a widget") + .setUnit("s") + // Uncomment to optionally provide advice on useful default explicit bucket boundaries + // .setExplicitBucketBoundariesAdvice(Arrays.asList(1.0, 2.0, 3.0)) + // Uncomment to optionally change the type to long + // .ofLongs() + .build(); + + // Record a measurement with no attributes or context. + // Attributes defaults to Attributes.empty(), context to Context.current(). + histogram.record(1.1); + + // Record a measurement with attributes, using pre-allocated attributes whenever possible. + histogram.record(2.2, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + histogram.record( + 3.2, Attributes.of(WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + + // Record a measurement with attributes, and context. + // Most users will opt to omit the context argument, preferring the default Context.current(). + histogram.record(4.4, WIDGET_RED_CIRCLE, customContext()); + } +} +``` + + +#### Gauge + +[DoubleGauge](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleGauge.html) +and +[LongGauge](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongGauge.html) +are used to record the latest value where spatial re-aggregation does not make +sense. + +The following code snippet explores gauge API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; +import static otel.Util.customContext; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.DoubleGauge; +import io.opentelemetry.api.metrics.Meter; + +public class GaugeUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void gaugeUsage(Meter meter) { + // Construct a gauge to record measurements as they occur, which cannot be spatially + // re-aggregated. + DoubleGauge gauge = + meter + .gaugeBuilder("fully.qualified.gauge") + .setDescription("The current temperature of the widget processing line") + .setUnit("K") + // Uncomment to optionally change the type to long + // .ofLongs() + .build(); + + // Record a measurement with no attributes or context. + // Attributes defaults to Attributes.empty(), context to Context.current(). + gauge.set(273.0); + + // Record a measurement with attributes, using pre-allocated attributes whenever possible. + gauge.set(273.0, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + gauge.set( + 273.0, + Attributes.of(WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + + // Record a measurement with attributes, and context. + // Most users will opt to omit the context argument, preferring the default Context.current(). + gauge.set(1L, WIDGET_RED_CIRCLE, customContext()); + } +} +``` + + +#### Async Gauge + +[ObservableDoubleGauge](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableDoubleGauge.html) +and +[ObservableLongGauge](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableLongGauge.html) +are used to observe the latest value where spatial re-aggregation does not make +sense. + +The following code snippet explores async gauge API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_SHAPE; +import static otel.Util.computeWidgetColor; +import static otel.Util.computeWidgetShape; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.ObservableDoubleGauge; +import java.util.concurrent.atomic.AtomicReference; + +public class AsyncGaugeUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void asyncGaugeUsage(Meter meter) { + AtomicReference processingLineTemp = new AtomicReference<>(273.0); + + // Construct an async counter to observe an existing counter in a callback + ObservableDoubleGauge asyncGauge = + meter + .gaugeBuilder("fully.qualified.gauge") + .setDescription("The current temperature of the widget processing line") + .setUnit("K") + // Uncomment to optionally change the type to long + // .ofLongs() + .buildWithCallback( + // the callback is invoked when a MetricReader reads metrics + observableMeasurement -> { + double currentWidgetCount = processingLineTemp.get(); + + // Record a measurement with no attributes. + // Attributes defaults to Attributes.empty(). + observableMeasurement.record(currentWidgetCount); + + // Record a measurement with attributes, using pre-allocated attributes whenever + // possible. + observableMeasurement.record(currentWidgetCount, WIDGET_RED_CIRCLE); + // Sometimes, attributes must be computed using application context. + observableMeasurement.record( + currentWidgetCount, + Attributes.of( + WIDGET_SHAPE, computeWidgetShape(), WIDGET_COLOR, computeWidgetColor())); + }); + + // Optionally close the gauge to unregister the callback when required + asyncGauge.close(); + } +} +``` + + +### LoggerProvider + +[LoggerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LoggerProvider.html) +is the API entry point for logs and provides [Loggers](#logger). See +[providers and scopes](#providers-and-scopes) for information on providers and +scopes. + +{{% alert %}} {{% param logBridgeWarning %}} {{% /alert %}} + +#### Logger + +[Logger](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/Logger.html) +is used to [emit log records](#logrecordbuilder) for an +[instrumentation scope](#providers-and-scopes). See +[providers and scopes](#providers-and-scopes) for information on providers and +scopes. + +#### LogRecordBuilder + +[LogRecordBuilder](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LogRecordBuilder.html) +is used to construct and emit log records. + +The following code snippet explores `LogRecordBuilder` API usage: + + + +```java +package otel; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.Value; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.api.logs.Severity; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class LogRecordUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void logRecordUsage(Logger logger) { + logger + .logRecordBuilder() + // Set body. Note, setBody(..) is called multiple times for demonstration purposes but only + // the last call is used. + // Set the body to a string, syntactic sugar for setBody(Value.of("log message")) + .setBody("log message") + // Optionally set the body to a Value to record arbitrarily complex structured data + .setBody(Value.of("log message")) + .setBody(Value.of(1L)) + .setBody(Value.of(1.1)) + .setBody(Value.of(true)) + .setBody(Value.of(new byte[] {'a', 'b', 'c'})) + .setBody(Value.of(Value.of("entry1"), Value.of("entry2"))) + .setBody( + Value.of( + Map.of( + "stringKey", + Value.of("entry1"), + "mapKey", + Value.of(Map.of("stringKey", Value.of("entry2")))))) + // Set severity + .setSeverity(Severity.DEBUG) + .setSeverityText("debug") + // Set timestamp + .setTimestamp(System.currentTimeMillis(), TimeUnit.MILLISECONDS) + // Optionally set the timestamp when the log was observed + .setObservedTimestamp(System.currentTimeMillis(), TimeUnit.MILLISECONDS) + // Set attributes + .setAttribute(AttributeKey.stringKey("com.acme.string-key"), "value") + .setAttribute(AttributeKey.booleanKey("com.acme.bool-key"), true) + .setAttribute(AttributeKey.longKey("com.acme.long-key"), 1L) + .setAttribute(AttributeKey.doubleKey("com.acme.double-key"), 1.1) + .setAttribute( + AttributeKey.stringArrayKey("com.acme.string-array-key"), + Arrays.asList("value1", "value2")) + .setAttribute( + AttributeKey.booleanArrayKey("come.acme.bool-array-key"), Arrays.asList(true, false)) + .setAttribute(AttributeKey.longArrayKey("come.acme.long-array-key"), Arrays.asList(1L, 2L)) + .setAttribute( + AttributeKey.doubleArrayKey("come.acme.double-array-key"), Arrays.asList(1.1, 2.2)) + .setAllAttributes(WIDGET_RED_CIRCLE) + // Uncomment to optionally explicitly set the context used to correlate with spans. If + // omitted, Context.current() is used. + // .setContext(context) + // Emit the log record + .emit(); + } +} +``` + + +### Noop implementation + +The `OpenTelemetry#noop()` method provides access to a noop implementation of +[OpenTelemetry](#opentelemetry) and all API components it provides access to. As +the name suggests, the noop implementation does nothing and is designed to have +no impact on performance. Instrumentation may see impact on performance even +when the noop is used if it is computing / allocating attribute values and other +data required to record the telemetry. The noop is a useful default instance of +`OpenTelemetry` when a user has not configured and installed a concrete +implementation such as the [SDK](../sdk/). + +The following code snippet explores `OpenTelemetry#noop()` API usage: + + + +```java +package otel; + +import static otel.Util.WIDGET_COLOR; +import static otel.Util.WIDGET_RED_CIRCLE; +import static otel.Util.WIDGET_SHAPE; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.api.metrics.DoubleGauge; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.LongCounter; +import io.opentelemetry.api.metrics.LongUpDownCounter; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; + +public class NoopUsage { + private static final String SCOPE_NAME = "fully.qualified.name"; + + public static void noopUsage() { + // Access the noop OpenTelemetry instance + OpenTelemetry noopOpenTelemetry = OpenTelemetry.noop(); + + // Noop tracing + Tracer noopTracer = OpenTelemetry.noop().getTracer(SCOPE_NAME); + noopTracer + .spanBuilder("span name") + .startSpan() + .setAttribute(WIDGET_SHAPE, "square") + .setStatus(StatusCode.OK) + .addEvent("event-name", Attributes.builder().put(WIDGET_COLOR, "red").build()) + .end(); + + // Noop metrics + Attributes attributes = WIDGET_RED_CIRCLE; + Meter noopMeter = OpenTelemetry.noop().getMeter(SCOPE_NAME); + DoubleHistogram histogram = noopMeter.histogramBuilder("fully.qualified.histogram").build(); + histogram.record(1.0, attributes); + // counter + LongCounter counter = noopMeter.counterBuilder("fully.qualified.counter").build(); + counter.add(1, attributes); + // async counter + noopMeter + .counterBuilder("fully.qualified.counter") + .buildWithCallback(observable -> observable.record(10, attributes)); + // updowncounter + LongUpDownCounter upDownCounter = + noopMeter.upDownCounterBuilder("fully.qualified.updowncounter").build(); + // async updowncounter + noopMeter + .upDownCounterBuilder("fully.qualified.updowncounter") + .buildWithCallback(observable -> observable.record(10, attributes)); + upDownCounter.add(-1, attributes); + // gauge + DoubleGauge gauge = noopMeter.gaugeBuilder("fully.qualified.gauge").build(); + gauge.set(1.1, attributes); + // async gauge + noopMeter + .gaugeBuilder("fully.qualified.gauge") + .buildWithCallback(observable -> observable.record(10, attributes)); + + // Noop logs + Logger noopLogger = OpenTelemetry.noop().getLogsBridge().get(SCOPE_NAME); + noopLogger + .logRecordBuilder() + .setBody("log message") + .setAttribute(WIDGET_SHAPE, "square") + .setSeverity(Severity.INFO) + .emit(); + } +} +``` + + +### Semantic attributes + +The [semantic conventions](/docs/specs/semconv/) describe how to collect +telemetry in a standardized way for common operations. This includes an +[attribute registry](/docs/specs/semconv/attributes-registry/), which enumerates +definitions for all attributes referenced in the conventions, organized by +domain. The +[semantic-conventions-java](https://github.com/open-telemetry/semantic-conventions-java) +project generates constants from the semantic conventions, which can be used to +help instrumentation conform: + +| Description | Artifact | +| -------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| Generated code for stable semantic conventions | `io.opentelemetry.semconv:opentelemetry-semconv:{{% param vers.semconv %}}-alpha` | +| Generated code for incubating semantic conventions | `io.opentelemetry.semconv:opentelemetry-semconv-incubating:{{% param vers.semconv %}}-alpha` | + +{{% alert %}} While both `opentelemetry-semconv` and +`opentelemetry-semconv-incubating` include the `-alpha` suffix and are subject +to breaking changes, the intent is to stabilize `opentelemetry-semconv` and +leave the `-alpha` suffix on `opentelemetry-semconv-incubating` permanently. +Libraries can use `opentelemetry-semconv-incubating` for testing, but should not +include it as a dependency: since attributes may come and go from version to +version, including it as a dependency may expose end users to runtime errors +when transitive version conflicts occur. {{% /alert %}} + +The attribute constants generated from semantic conventions are instances of +`AttributeKey`, and can be used anywhere the OpenTelemetry API accepts +attributes. + +The following code snippet explores semantic convention attribute API usage: + + + +```java +package otel; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes; + +public class SemanticAttributesUsage { + public static void semanticAttributesUsage() { + // Semantic attributes are organized by top-level domain and whether they are stable or + // incubating. + // For example: + // - stable attributes starting with http.* are in the HttpAttributes class. + // - stable attributes starting with server.* are in the ServerAttributes class. + // - incubating attributes starting with http.* are in the HttpIncubatingAttributes class. + // Attribute keys which define an enumeration of values are accessible in an inner + // {AttributeKey}Values class. + // For example, the enumeration of http.request.method values is available in the + // HttpAttributes.HttpRequestMethodValues class. + Attributes attributes = + Attributes.builder() + .put(HttpAttributes.HTTP_REQUEST_METHOD, HttpAttributes.HttpRequestMethodValues.GET) + .put(HttpAttributes.HTTP_ROUTE, "/users/:id") + .put(ServerAttributes.SERVER_ADDRESS, "example") + .put(ServerAttributes.SERVER_PORT, 8080L) + .put(HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, 1024) + .build(); + } +} +``` + + +### Baggage + +[Baggage](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/baggage/Baggage.html) +is a bundle of application defined key-value pairs associated with a distributed +request or workflow execution. Baggage keys and values are strings, and values +have optional string metadata. Telemetry can be enriched with data from baggage +by configuring the [SDK](../sdk/) to add entries as attributes to spans, +metrics, and log records. The baggage API is built on top of +[context](#context), which allows span context to be implicitly passed around an +application and across threads. Most of the context API usage guidance applies +to baggage. + +Baggage is propagated across application boundaries with the +[W3CBaggagePropagator](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/baggage/propagation/W3CBaggagePropagator.html) +(see [TextMapPropagator](../sdk/#textmappropagator) for details). + +The following code snippet explores `Baggage` API usage: + + + +```java +package otel; + +import static io.opentelemetry.context.Context.current; + +import io.opentelemetry.api.baggage.Baggage; +import io.opentelemetry.api.baggage.BaggageEntry; +import io.opentelemetry.api.baggage.BaggageEntryMetadata; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Scope; +import java.util.Map; +import java.util.stream.Collectors; + +public class BaggageUsage { + private static final Attributes WIDGET_RED_CIRCLE = Util.WIDGET_RED_CIRCLE; + + public static void baggageUsage() { + // Access current baggage with Baggage.current() + // output => context baggage: {} + Baggage currentBaggage = Baggage.current(); + System.out.println("current baggage: " + asString(currentBaggage)); + // ...or from a Context + currentBaggage = Baggage.fromContext(current()); + + // Baggage has a variety of methods for manipulating and reading data. + // Convert to builder and add entries: + Baggage newBaggage = + Baggage.current().toBuilder() + .put("shopId", "abc123") + .put("shopName", "opentelemetry-demo", BaggageEntryMetadata.create("metadata")) + .build(); + // ...or uncomment to start from empty + // newBaggage = Baggage.empty().toBuilder().put("shopId", "abc123").build(); + // output => new baggage: {shopId=abc123(), shopName=opentelemetry-demo(metadata)} + System.out.println("new baggage: " + asString(newBaggage)); + // Read an entry: + String shopIdValue = newBaggage.getEntryValue("shopId"); + // Inspect size: + int size = newBaggage.size(); + boolean isEmpty = newBaggage.isEmpty(); + // Convert to map representation: + Map map = newBaggage.asMap(); + // Iterate through entries: + newBaggage.forEach((s, baggageEntry) -> {}); + + // The current baggage still doesn't contain the new entries + // output => context baggage: {} + System.out.println("current baggage: " + asString(Baggage.current())); + + // Calling Baggage.makeCurrent() sets Baggage.current() to the baggage until the scope is + // closed, upon which Baggage.current() is restored to the state prior to when + // Baggage.makeCurrent() was called. + try (Scope scope = newBaggage.makeCurrent()) { + // The current baggage now contains the added value + // output => context baggage: {shopId=abc123(), shopName=opentelemetry-demo(metadata)} + System.out.println("current baggage: " + asString(Baggage.current())); + } + + // The current baggage no longer contains the new entries: + // output => context baggage: {} + System.out.println("current baggage: " + asString(Baggage.current())); + } + + private static String asString(Baggage baggage) { + return baggage.asMap().entrySet().stream() + .map( + entry -> + String.format( + "%s=%s(%s)", + entry.getKey(), + entry.getValue().getValue(), + entry.getValue().getMetadata().getValue())) + .collect(Collectors.joining(", ", "{", "}")); + } +} +``` + + +## Incubating API + +The `io.opentelemetry:opentelemetry-api-incubator:{{% param vers.otel %}}-alpha` +artifact contains experimental trace, metric, log, and context APIs which. +Incubating APIs may have breaking API changes in minor releases. Often, these +represent experimental specification features or API designs we want to vet with +user feedback before committing to. We encourage users to try these APIs and +open issues with any feedback (positive or negative). Libraries should not +depend on the incubating APIs, since users may be exposed to runtime errors when +transitive version conflicts occur. + +See +[incubator README](https://github.com/open-telemetry/opentelemetry-java/tree/main/api/incubator) +for available APIs and sample usage. diff --git a/content/en/docs/languages/java/api.md b/content/en/docs/languages/java/api.md index 5a77f07f940e..8c8e8f079851 100644 --- a/content/en/docs/languages/java/api.md +++ b/content/en/docs/languages/java/api.md @@ -1,6 +1,6 @@ --- -title: API reference -linkTitle: API +title: Javadoc API reference +linkTitle: Javadoc redirect: https://javadoc.io/doc/io.opentelemetry manualLinkTarget: _blank _build: { render: link } diff --git a/content/en/docs/languages/java/configuration.md b/content/en/docs/languages/java/configuration.md index f73a996a8786..5668297caa6d 100644 --- a/content/en/docs/languages/java/configuration.md +++ b/content/en/docs/languages/java/configuration.md @@ -1,7 +1,7 @@ --- title: Configure the SDK linkTitle: Configure the SDK -weight: 12 +weight: 13 aliases: [config] # prettier-ignore cSpell:ignore: authservice autoconfigured blrp Customizer Dotel ignore LOWMEMORY myservice ottrace PKCS retryable tracepropagators @@ -11,7 +11,7 @@ cSpell:ignore: authservice autoconfigured blrp Customizer Dotel ignore LOWMEMORY The [SDK](../sdk/) is the built-in reference implementation of the -[API](../instrumentation/), processing and exporting telemetry produced by +[API](../api-components/), processing and exporting telemetry produced by instrumentation API calls. Configuring the SDK to process and export appropriately is an essential step to integrating OpenTelemetry into an application. diff --git a/content/en/docs/languages/java/instrumentation.md b/content/en/docs/languages/java/instrumentation.md index f106bfc12bcc..9cf2e297ac27 100644 --- a/content/en/docs/languages/java/instrumentation.md +++ b/content/en/docs/languages/java/instrumentation.md @@ -1,1102 +1,201 @@ --- -title: Instrumentation +title: Instrumentation ecosystem aliases: - /docs/java/getting_started - /docs/java/manual_instrumentation - manual - manual_instrumentation -weight: 20 -description: Manual instrumentation for OpenTelemetry Java -# prettier-ignore -cSpell:ignore: Autowired customizer logback loggable multivalued rolldice springframework + - libraries +weight: 10 +description: Instrumentation ecosystem in OpenTelemetry Java +cSpell:ignore: Logback logback --- -{{% docs/languages/instrumentation-intro %}} +Instrumentation records telemetry using the [API](../api-components/). The +[SDK](../sdk/) is the built-in reference implementation of the API, and is +[configured](../configuration/) to process and export the telemetry produced by +instrumentation API calls. This page discusses the OpenTelemetry ecosystem in +OpenTelemetry Java, including resources for end users and cross-cutting +instrumentation topics: -{{% alert title="Note" color="info" %}} See [Manage Telemetry with SDK](../sdk/) -for a conceptual overview of OpenTelemetry Java SDK concepts. See -**[Configure the SDK](../configuration/)** for details on SDK configuration, -including -[zero-code SDK autoconfigure](../configuration/#zero-code-sdk-autoconfigure). -{{% /alert %}} +- [Instrumentation categories](#instrumentation-categories): There are a variety + of categories of instrumentation addressing different use cases and + installation patterns. +- [Context propagation](#context-propagation): Context propagation provides + correlation between traces, metrics, and logs, allowing the signals to + complement each other. +- [Semantic conventions](#semantic-conventions): The semantic conventions define + how to produce telemetry for standard operations. +- [Log instrumentation](#log-instrumentation): The semantic conventions define + how to produce telemetry for standard operations. + +{{% alert %}} While [instrumentation categories](#instrumentation-categories) +enumerates several options for instrumenting an application, we recommend users +start with the [Java agent](#zero-code-java-agent). The Java agent has a simple +installation process, and automatically detects and installs instrumentation +from a large library. {{% /alert %}} + +## Instrumentation categories + +There are several categories of instrumentation: + +- [Zero-code: Java agent](#zero-code-java-agent) is a form of zero-code + instrumentation **[1]** that dynamically manipulates application bytecode. +- [Zero-code: Spring Boot starter](#zero-code-spring-boot-starter) is a form of + zero-code instrumentation **[1]** that leverages spring autoconfigure to + install [library instrumentation](#library-instrumentation). +- [Library instrumentation](#library-instrumentation) wraps or uses extension + points to instrument a library, requiring users to install and/or adapt + library usage. +- [Native instrumentation](#native-instrumentation) is built directly into + libraries and frameworks. +- [Manual instrumentation](#manual-instrumentation) is written by application + authors, and typically specific to the application domain. + +**[1]**: Zero-code instrumentation is installed automatically based on detected +libraries / frameworks. + +The +[opentelemetry-java-instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +project contains the source code for Java agent, Spring Boot starter, and +Library instrumentation. + +### Zero-code: Java agent + +The Java agent is a form of zero-code +[automatic instrumentation](/docs/specs/otel/glossary/#automatic-instrumentation) +that dynamically manipulates application bytecode. + +For a list of libraries instrumented by the Java agent, see the +"Auto-instrumented versions" column on +[supported libraries](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md). + +See [Java agent](/docs/zero-code/java/agent/) for more details. + +### Zero-code: Spring Boot starter + +The Spring Boot starter is a form of zero-code +[automatic instrumentation](/docs/specs/otel/glossary/#automatic-instrumentation) +that leverages spring autoconfigure to install +[library instrumentation](#library-instrumentation). + +See [Spring Boot starter](/docs/zero-code/java/spring-boot-starter/) for +details. + +### Library instrumentation + +[Library instrumentation](/docs/specs/otel/glossary/#instrumentation-library) +wraps or uses extension points to instrument a library, requiring users to +install and/or adapt library usage. + +For a list of instrumentation libraries, see the "Standalone Library +Instrumentation" column on +[supported libraries](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md). + +### Native instrumentation + +[Native instrumentation](/docs/specs/otel/glossary/#natively-instrumented) is +built directly into libraries or frameworks. OpenTelemetry encourages library +authors to add native instrumentation using the [API](../api-components/). In +the long term, we hope the native instrumentation becomes the norm, and view the +instrumentation maintained by OpenTelemetry in +[opentelemetry-java-instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +as a temporary means of filling the gap. + +{{% docs/languages/native-libraries "java" %}} + +### Manual instrumentation + +[Manual instrumentation](/docs/specs/otel/glossary/#manual-instrumentation) is +written by application authors, and typically specific to the application +domain. + +### Shims + +A shim is instrumentation that bridges data from one observability library to +another, typically _from_ some library into OpenTelemetry. + +Shims maintained in the OpenTelemetry Java ecosystem: + +| Description | Documentation | Signal(s) | Artifact | +| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Bridge [OpenTracing](https://opentracing.io/) into OpenTelemetry | [README](https://github.com/open-telemetry/opentelemetry-java/tree/main/opentracing-shim) | Traces | `io.opentelemetry:opentelemetry-opentracing-shim:{{% param vers.otel %}}` | +| Bridge [Opencensus](https://opencensus.io/) into OpenTelemetry | [README](https://github.com/open-telemetry/opentelemetry-java/tree/main/opencensus-shim) | Traces, Metrics | `io.opentelemetry:opentelemetry-opencensus-shim:{{% param vers.otel %}}-alpha` | +| Bridge [Micrometer](https://micrometer.io/) into OpenTelemetry | [README](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/micrometer/micrometer-1.5/library) | Metrics | `io.opentelemetry.instrumentation:opentelemetry-micrometer-1.5:{{% param vers.instrumentation %}}-alpha` | +| Bridge [JMX](https://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html) into OpenTelemetry | [README](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/jmx-metrics/javaagent/README.md) | Metrics | `io.opentelemetry.instrumentation:opentelemetry-jmx-metrics:{{% param vers.instrumentation %}}-alpha` | +| Bridge OpenTelemetry into [Prometheus Java client](https://github.com/prometheus/client_java) | [README](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/prometheus-client-bridge) | Metrics | `io.opentelemetry.contrib:opentelemetry-prometheus-client-bridge:{{% param vers.contrib %}}-alpha` | +| Bridge OpenTelemetry into [Micrometer](https://micrometer.io/) | [README](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/micrometer-meter-provider) | Metrics | `io.opentelemetry.contrib:opentelemetry-micrometer-meter-provider:{{% param vers.contrib %}}-alpha` | +| Bridge [Log4j](https://logging.apache.org/log4j/2.x/index.html) into OpenTelemetry | [README](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/log4j/log4j-appender-2.17/library) | Logs | `io.opentelemetry.instrumentation:opentelemetry-log4j-appender-2.17:{{% param vers.instrumentation %}}-alpha` | +| Bridge [Logback](https://logback.qos.ch/) into OpenTelemetry | [README](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/logback/logback-appender-1.0/library) | Logs | `io.opentelemetry.instrumentation:opentelemetry-logback-appender-1.0:{{% param vers.instrumentation %}}-alpha` | +| Bridge OpenTelemetry context into [Log4j](https://logging.apache.org/log4j/2.x/index.html) | [README](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure) | Context | `io.opentelemetry.instrumentation:opentelemetry-log4j-context-data-2.17-autoconfigure:{{% param vers.instrumentation %}}-alpha` | +| Bridge OpenTelemetry context into [Logback](https://logback.qos.ch/) | [README](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/logback/logback-mdc-1.0/library) | Context | `io.opentelemetry.instrumentation:opentelemetry-logback-mdc-1.0:{{% param vers.instrumentation %}}-alpha` | + +## Context propagation + +The OpenTelemetry APIs are designed to be complementary, with the whole greater +than the sum of the parts. Each signal has its own strengths, and collectively +stitch together a compelling observability story. + +Importantly, the data from the various signals are linked together through trace +context: + +- Spans are related to other spans through span parent and links, which each + record trace context of related spans. +- Metrics are related to spans through + [exemplars](/docs/specs/otel/metrics/data-model/#exemplars), which record + trace context of a particular measurement. +- Logs are related to spans by recording trace context on log records. + +For this correlation to work, trace context must be propagated throughout an +application (across function calls and threads), and across application +boundaries. The [context API](../api-components/#context-api) facilitates this. +Instrumentation needs to be written in a manner which is context aware: -{{% alert title="Note" color="info" %}} +- Libraries that represent the entry point to an application (i.e. HTTP servers, + message consumers, etc.) should + [extract context](../api-components/#contextpropagators) from incoming + messages. +- Libraries that represent an exit point from an application (i.e. HTTP clients, + message producers, etc.) should + [inject context](../api-components/#contextpropagators) into outgoing + messages. +- Libraries should implicitly or explicitly pass + [Context](../api-components/#context) through the callstack and across any + threads. + +## Semantic conventions -On this page you will learn how you can add traces, metrics and logs to your -code _manually_. But, you are not limited to only use one kind of -instrumentation: use [zero-code instrumentation](/docs/zero-code/java/agent/) to -get started and then enrich your code with manual instrumentation as needed. +The [semantic conventions](/docs/specs/semconv/) define how to produce telemetry +for standard operations. Among other things, the semantic conventions specify +span names, span kinds, metric instruments, metric units, metric types, and +attribute key, value, and requirement levels. -Note, that especially if you cannot modify the source code of your app, you can -skip manual instrumentation and only use automatic instrumentation. - -Also, for libraries your code depends on, you don't have to write -instrumentation code yourself, since they might come with OpenTelemetry built-in -_natively_ or you can make use of [instrumentation libraries](../libraries/). - -{{% /alert %}} - -## Example app preparation {#example-app} - -This page uses a modified version of the example app from -[Getting Started](../getting-started/) to help you learn about manual -instrumentation. - -You don't have to use the example app: if you want to instrument your own app or -library, follow the instructions here to adapt the process to your own code. - -### Prerequisites - -For running the example app, ensure that you have the following installed -locally: - -- Java JDK 17+, due to the use of Spring Boot 3. OpenTelemetry Java itself only - [requires Java 8+][java-vers]. -- [Gradle](https://gradle.org/). - -### Dependencies {#example-app-dependencies} - -To begin, set up an environment in a new directory called `java-simple`. Within -that directory, create a file called `build.gradle.kts` with the following -content: - -```kotlin -plugins { - id("java") - id("org.springframework.boot") version "3.0.6" - id("io.spring.dependency-management") version "1.1.0" -} - -sourceSets { - main { - java.setSrcDirs(setOf(".")) - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation("org.springframework.boot:spring-boot-starter-web") -} -``` - -### Create and launch an HTTP Server - -To highlight the difference between instrumenting a _library_ and a standalone -_app_, split out the dice rolling into a _library_ class, which then will be -imported as a dependency by the app. - -Create the _library file_ name `Dice.java` and add the following code to it: - -```java -package otel; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -public class Dice { - - private int min; - private int max; - - public Dice(int min, int max) { - this.min = min; - this.max = max; - } - - public List rollTheDice(int rolls) { - List results = new ArrayList(); - for (int i = 0; i < rolls; i++) { - results.add(this.rollOnce()); - } - return results; - } - - private int rollOnce() { - return ThreadLocalRandom.current().nextInt(this.min, this.max + 1); - } -} -``` - -Create the app files `DiceApplication.java` and `RollController.java` and add -the following code to them: - -```java -// DiceApplication.java -package otel; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.Banner; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DiceApplication { - public static void main(String[] args) { - - SpringApplication app = new SpringApplication(DiceApplication.class); - app.setBannerMode(Banner.Mode.OFF); - app.run(args); - } -} -``` - -```java -// RollController.java -package otel; - -import java.util.List; -import java.util.Optional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; - -import otel.Dice; - -@RestController -public class RollController { - private static final Logger logger = LoggerFactory.getLogger(RollController.class); - - @GetMapping("/rolldice") - public List index(@RequestParam("player") Optional player, - @RequestParam("rolls") Optional rolls) { - - if (!rolls.isPresent()) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing rolls parameter", null); - } - - List result = new Dice(1, 6).rollTheDice(rolls.get()); - - if (player.isPresent()) { - logger.info("{} is rolling the dice: {}", player.get(), result); - } else { - logger.info("Anonymous player is rolling the dice: {}", result); - } - return result; - } -} -``` - -To ensure that it is working, run the application with the following command and -open in your web browser: - -```shell -gradle assemble -java -jar ./build/libs/java-simple.jar -``` - -You should get a list of 12 numbers in your browser window, for example: - -```text -[5,6,5,3,6,1,2,5,4,4,2,4] -``` - -## Manual instrumentation setup - -For both library and app instrumentation, the first step is to install the -dependencies for the OpenTelemetry API. - -Throughout this documentation you will add dependencies. For a full list of -artifact coordinates, see [releases]. For semantic convention releases, see -[semantic-conventions-java]. - -[releases]: https://github.com/open-telemetry/opentelemetry-java#releases -[semantic-conventions-java]: - https://github.com/open-telemetry/semantic-conventions-java/releases - -### Dependency management - -A Bill of Material -([BOM](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#bill-of-materials-bom-poms)) -ensures that versions of dependencies (including transitive ones) are aligned. -Importing the `opentelemetry-bom` BOM is important to ensure version alignment -across all OpenTelemetry dependencies. - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin { hl_lines=["1-5",9] } -dependencyManagement { - imports { - mavenBom("io.opentelemetry:opentelemetry-bom:{{% param vers.otel %}}") - } -} - -dependencies { - implementation("org.springframework.boot:spring-boot-starter-web"); - implementation("io.opentelemetry:opentelemetry-api"); -} -``` - -If you are not using Spring and its `io.spring.dependency-management` dependency -management plugin, install the OpenTelemetry BOM and API using Gradle -dependencies only. - -```kotlin -dependencies { - implementation(platform("io.opentelemetry:opentelemetry-bom:{{% param vers.otel %}}")); - implementation("io.opentelemetry:opentelemetry-api"); -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - - io.opentelemetry - opentelemetry-bom - {{% param vers.otel %}} - pom - import - - - - - - io.opentelemetry - opentelemetry-api - - - -``` - -{{% /tab %}} {{% /tabpane %}} - -## Traces - -The following sections describe the OpenTelemetry Java tracing API. See -[SdkTracerProvider](../sdk/#sdktracerprovider) for an overview of trace SDK -concepts and configuration. - -### Acquiring a tracer - -To do [Tracing](/docs/concepts/signals/traces/) you'll need to acquire a -[`Tracer`](/docs/concepts/signals/traces/#tracer). - -**Note:** Methods of the OpenTelemetry SDK should never be called. - -First, a `Tracer` must be acquired, which is responsible for creating spans and -interacting with the [Context](#context-propagation). A tracer is acquired by -using the OpenTelemetry API specifying the name and version of the [library -instrumenting][instrumentation library] the [instrumented library] or application -to be monitored. More information is available in the specification chapter [Obtaining -a -Tracer]. - -Anywhere in your application where you write manual tracing code should call -`getTracer` to acquire a tracer. For example: - -```java -import io.opentelemetry.api.trace.Tracer; - -Tracer tracer = openTelemetry.getTracer("instrumentation-scope-name", "instrumentation-scope-version"); -``` - -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. This will help later help determining what the -source of telemetry is. While the name is required, the version is still -recommended despite being optional. Note, that all `Tracer`s that are created by -a single `OpenTelemetry` instance will interoperate, regardless of name. - -It's generally recommended to call `getTracer` in your app when you need it -rather than exporting the `tracer` instance to the rest of your app. This helps -avoid trickier application load issues when other required dependencies are -involved. - -In the case of the [example app](#example-app), there are two places where a -tracer may be acquired with an appropriate Instrumentation Scope: - -First, in the `index` method of the `RollController` as follows: - -```java { hl_lines=["4-6",11,"13-16"] } -package otel; - -// ... -import org.springframework.beans.factory.annotation.Autowired; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; - -@RestController -public class RollController { - private static final Logger logger = LoggerFactory.getLogger(RollController.class); - private final Tracer tracer; - - @Autowired - RollController(OpenTelemetry openTelemetry) { - tracer = openTelemetry.getTracer(RollController.class.getName(), "0.1.0"); - } - // ... -} -``` - -And second, in the _library file_ `Dice.java`: - -```java { hl_lines=["2-3","9-19"]} -// ... -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; - -public class Dice { - - private int min; - private int max; - private Tracer tracer; - - public Dice(int min, int max, OpenTelemetry openTelemetry) { - this.min = min; - this.max = max; - this.tracer = openTelemetry.getTracer(Dice.class.getName(), "0.1.0"); - } - - public Dice(int min, int max) { - this(min, max, OpenTelemetry.noop()); - } - - // ... -} -``` - -As an aside, if you are writing library instrumentation, it is strongly -recommended that you provide your users the ability to inject an instance of -`OpenTelemetry` into your instrumentation code. If this is not possible for some -reason, you can fall back to using an instance from the `GlobalOpenTelemetry` -class: - -```java -import io.opentelemetry.api.GlobalOpenTelemetry; - -Tracer tracer = GlobalOpenTelemetry.getTracer("instrumentation-scope-name", "instrumentation-scope-version"); -``` - -Note that you can't force end users to configure the global, so this is the most -brittle option for library instrumentation. - -### Acquiring a tracer in Java agent - -If you are using the [Java agent], you can acquire a `Tracer` from the global OpenTelemetry -instance: - -```java -import io.opentelemetry.api.GlobalOpenTelemetry; - -Tracer tracer = GlobalOpenTelemetry.getTracer("application"); -``` - -If you are using Spring Boot, you can add the following bean to your -`@SpringBootApplication` class - to acquire a `Tracer` as in the -[Spring Boot starter](#acquiring-a-tracer-in-spring-boot-starter) section below: - -```java -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.GlobalOpenTelemetry; - -@Configuration -public class OpenTelemetryConfig { - @Bean - public OpenTelemetry openTelemetry() { - return GlobalOpenTelemetry.get(); - } -} -``` - -### Acquiring a tracer in Spring Boot starter - -If you are using the [Spring Boot starter], you can acquire a `Tracer` from the -autowired OpenTelemetry instance: - -```java -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; - -@Controller -public class MyController { - private final Tracer tracer; - - public MyController(OpenTelemetry openTelemetry) { - this.tracer = openTelemetry.getTracer("application"); - } -} -``` - -### Create Spans - -Now that you have [tracers](/docs/concepts/signals/traces/#tracer) initialized, -you can create [spans](/docs/concepts/signals/traces/#spans). - -To create [Spans](/docs/concepts/signals/traces/#spans), you only need to -specify the name of the span. The start and end time of the span is -automatically set by the OpenTelemetry SDK. - -The code below illustrates how to create a span: - -```java { hl_lines=["1-2","8-11","25-30"] } -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; - -// ... - @GetMapping("/rolldice") - public List index(@RequestParam("player") Optional player, - @RequestParam("rolls") Optional rolls) { - Span span = tracer.spanBuilder("rollTheDice").startSpan(); - - // Make the span the current span - try (Scope scope = span.makeCurrent()) { - - if (!rolls.isPresent()) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing rolls parameter", null); - } - - List result = new Dice(1, 6).rollTheDice(rolls.get()); - - if (player.isPresent()) { - logger.info("{} is rolling the dice: {}", player.get(), result); - } else { - logger.info("Anonymous player is rolling the dice: {}", result); - } - return result; - } catch(Throwable t) { - span.recordException(t); - throw t; - } finally { - span.end(); - } - } -``` - -It's required to call `end()` to end the span when you want it to end. - -If you followed the instructions using the [example app](#example-app) up to -this point, you can copy the code above into the `index` method of the -`RollController`. You should now be able to see spans emitted from your app. - -Start your app as follows, and then send it requests by visiting - with your browser or `curl`: - -```shell -gradle assemble -env \ -OTEL_SERVICE_NAME=dice-server \ -OTEL_TRACES_EXPORTER=logging \ -OTEL_METRICS_EXPORTER=logging \ -OTEL_LOGS_EXPORTER=logging \ -java -jar ./build/libs/java-simple.jar -``` - -After a while, you should see the spans printed in the console by the -`LoggingSpanExporter`, something like this: - -```log -2023-08-02T17:22:22.658+02:00 INFO 2313 --- [nio-8080-exec-1] i.o.e.logging.LoggingSpanExporter : 'rollTheDice' : 565232b11b9933fa6be8d6c4a1307fe2 6e1e011e2e8c020b INTERNAL [tracer: otel.RollController:0.1.0] {} -``` - -### Create nested Spans - -Most of the time, we want to correlate -[spans](/docs/concepts/signals/traces/#spans) for nested operations. -OpenTelemetry supports tracing within processes and across remote processes. For -more details how to share context between remote processes, see -[Context Propagation](#context-propagation). - -For example in the `Dice` class method `rollTheDice` calling method `rollOnce`, -the spans could be manually linked in the following way: - -```java { hl_lines=["1-2","5","7","9","12-14","17-21","23-25"]} -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -// ... - public List rollTheDice(int rolls) { - Span parentSpan = tracer.spanBuilder("parent").startSpan(); - List results = new ArrayList(); - try { - for (int i = 0; i < rolls; i++) { - results.add(this.rollOnce(parentSpan)); - } - return results; - } finally { - parentSpan.end(); - } - } - - private int rollOnce(Span parentSpan) { - Span childSpan = tracer.spanBuilder("child") - .setParent(Context.current().with(parentSpan)) - .startSpan(); - try { - return ThreadLocalRandom.current().nextInt(this.min, this.max + 1); - } finally { - childSpan.end(); - } - } -``` - -The OpenTelemetry API offers also an automated way to propagate the parent span -on the current thread: - -```java { hl_lines=["1-2","5-6","12-14","18-22","24-26"]} -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -// ... - public List rollTheDice(int rolls) { - Span parentSpan = tracer.spanBuilder("parent").startSpan(); - try (Scope scope = parentSpan.makeCurrent()) { - List results = new ArrayList(); - for (int i = 0; i < rolls; i++) { - results.add(this.rollOnce()); - } - return results; - } finally { - parentSpan.end(); - } - } - - private int rollOnce() { - Span childSpan = tracer.spanBuilder("child") - // NOTE: setParent(...) is not required; - // `Span.current()` is automatically added as the parent - .startSpan(); - try(Scope scope = childSpan.makeCurrent()) { - return ThreadLocalRandom.current().nextInt(this.min, this.max + 1); - } finally { - childSpan.end(); - } - } -} -``` - -To link spans from remote processes, it is sufficient to set the -[Remote Context](#context-propagation) as parent. - -```java -Span childRemoteParent = tracer.spanBuilder("Child").setParent(remoteContext).startSpan(); -``` - -### Get the current span - -Sometimes it's helpful to do something with the current/active -[span](/docs/concepts/signals/traces/#spans) at a particular point in program -execution. - -```java -Span span = Span.current() -``` - -And if you want the current span for a particular `Context` object: - -```java -Span span = Span.fromContext(context) -``` - -### Span Attributes - -In OpenTelemetry [spans](/docs/concepts/signals/traces/#spans) can be created -freely and it's up to the implementor to annotate them with attributes specific -to the represented operation. -[Attributes](/docs/concepts/signals/traces/#attributes) provide additional -context on a span about the specific operation it tracks, such as results or -operation properties. - -```java -Span span = tracer.spanBuilder("/resource/path").setSpanKind(SpanKind.CLIENT).startSpan(); -span.setAttribute("http.method", "GET"); -span.setAttribute("http.url", url.toString()); -``` - -### Semantic Attributes - -There are semantic conventions for spans representing operations in well-known -protocols like HTTP or database calls. Semantic conventions for these spans are -defined in the specification at -[Trace Semantic Conventions](/docs/specs/semconv/general/trace/). - -First add the semantic conventions as a dependency to your application: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin -dependencies { - implementation("io.opentelemetry.semconv:opentelemetry-semconv:{{% param vers.semconv %}}-alpha") -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - io.opentelemetry.semconv - opentelemetry-semconv - {{% param vers.semconv %}}-alpha - -``` - -{{% /tab %}} {{< /tabpane>}} - -Finally, you can update your file to include semantic attributes: - -```java -Span span = tracer.spanBuilder("/resource/path").setSpanKind(SpanKind.CLIENT).startSpan(); -span.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); -span.setAttribute(SemanticAttributes.HTTP_URL, url.toString()); -``` - -### Create Spans with events - -[Spans](/docs/concepts/signals/traces/#spans) can be annotated with named events -(called [Span Events](/docs/concepts/signals/traces/#span-events)) that can -carry zero or more [Span Attributes](#span-attributes), each of which itself is -a key:value map paired automatically with a timestamp. - -```java -span.addEvent("Init"); -... -span.addEvent("End"); -``` - -```java -Attributes eventAttributes = Attributes.of( - AttributeKey.stringKey("key"), "value", - AttributeKey.longKey("result"), 0L); - -span.addEvent("End Computation", eventAttributes); -``` - -### Create Spans with links - -A [Span](/docs/concepts/signals/traces/#spans) may be linked to zero or more -other Spans that are causally related via a -[Span Link](/docs/concepts/signals/traces/#span-links). Links can be used to -represent batched operations where a Span was initiated by multiple initiating -Spans, each representing a single incoming item being processed in the batch. - -```java -Span child = tracer.spanBuilder("childWithLink") - .addLink(parentSpan1.getSpanContext()) - .addLink(parentSpan2.getSpanContext()) - .addLink(parentSpan3.getSpanContext()) - .addLink(remoteSpanContext) - .startSpan(); -``` - -For more details how to read context from remote processes, see -[Context Propagation](#context-propagation). - -### Set span status - -A [status](/docs/concepts/signals/traces/#span-status) can be set on a -[span](/docs/concepts/signals/traces/#spans), typically used to specify that a -span has not completed successfully - `SpanStatus.Error`. In rare scenarios, you -could override the `Error` status with `OK`, but don't set `OK` on -successfully-completed spans. - -The status can be set at any time before the span is finished: - -```java -Span span = tracer.spanBuilder("my span").startSpan(); -// put the span into the current Context -try (Scope scope = span.makeCurrent()) { - // do something -} catch (Throwable t) { - span.setStatus(StatusCode.ERROR, "Something bad happened!"); - throw t; -} finally { - span.end(); // Cannot set a span after this call -} -``` - -### Record exceptions in spans - -It can be a good idea to record exceptions when they happen. It's recommended to -do this in conjunction with setting [span status](#set-span-status). - -```java -Span span = tracer.spanBuilder("my span").startSpan(); -// put the span into the current Context -try (Scope scope = span.makeCurrent()) { - // do something -} catch (Throwable throwable) { - span.setStatus(StatusCode.ERROR, "Something bad happened!"); - span.recordException(throwable); -} finally { - span.end(); // Cannot set a span after this call -} -``` - -This will capture things like the current stack trace in the span. - -### Context Propagation - -OpenTelemetry provides a text-based approach to propagate context to remote -services using the [W3C Trace Context](https://www.w3.org/TR/trace-context/) -HTTP headers. - -### Context propagation between threads - -The following example demonstrates how to propagate the context between threads: - -```java -io.opentelemetry.context.Context context = io.opentelemetry.context.Context.current(); -Thread thread = new Thread(context.wrap(new Runnable() { - @Override - public void run() { - // Code for which you want to propagate the context - } -})); -thread.start(); -``` - -### Context propagation between HTTP requests - -The following presents an example of an outgoing HTTP request using -`HttpURLConnection`. - -```java -// Tell OpenTelemetry to inject the context in the HTTP headers -TextMapSetter setter = - new TextMapSetter() { - @Override - public void set(HttpURLConnection carrier, String key, String value) { - // Insert the context as Header - carrier.setRequestProperty(key, value); - } -}; - -URL url = new URL("http://127.0.0.1:8080/resource"); -Span outGoing = tracer.spanBuilder("/resource").setSpanKind(SpanKind.CLIENT).startSpan(); -try (Scope scope = outGoing.makeCurrent()) { - // Use the Semantic Conventions. - // (Note that to set these, Span does not *need* to be the current instance in Context or Scope.) - outGoing.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); - outGoing.setAttribute(SemanticAttributes.HTTP_URL, url.toString()); - HttpURLConnection transportLayer = (HttpURLConnection) url.openConnection(); - // Inject the request with the *current* Context, which contains our current Span. - openTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), transportLayer, setter); - // Make outgoing call -} finally { - outGoing.end(); -} -... -``` - -Similarly, the text-based approach can be used to read the W3C Trace Context -from incoming requests. The following presents an example of processing an -incoming HTTP request using [HttpExchange][]. - -```java -TextMapGetter getter = - new TextMapGetter<>() { - @Override - public String get(HttpExchange carrier, String key) { - if (carrier.getRequestHeaders().containsKey(key)) { - return carrier.getRequestHeaders().get(key).get(0); - } - return null; - } - - @Override - public Iterable keys(HttpExchange carrier) { - return carrier.getRequestHeaders().keySet(); - } -}; -... -public void handle(HttpExchange httpExchange) { - // Extract the SpanContext and other elements from the request. - Context extractedContext = openTelemetry.getPropagators().getTextMapPropagator() - .extract(Context.current(), httpExchange, getter); - try (Scope scope = extractedContext.makeCurrent()) { - // Automatically use the extracted SpanContext as parent. - Span serverSpan = tracer.spanBuilder("GET /resource") - .setSpanKind(SpanKind.SERVER) - .startSpan(); - try { - // Add the attributes defined in the Semantic Conventions - serverSpan.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); - serverSpan.setAttribute(SemanticAttributes.HTTP_SCHEME, "http"); - serverSpan.setAttribute(SemanticAttributes.HTTP_HOST, "localhost:8080"); - serverSpan.setAttribute(SemanticAttributes.HTTP_TARGET, "/resource"); - // Serve the request - ... - } finally { - serverSpan.end(); - } - } -} -``` - -The following code presents an example to read the W3C Trace Context from -incoming request, add spans, and further propagate the context. The example -utilizes -[HttpHeaders](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpHeaders.html) -to fetch the traceparent header for context propagation. - -```java -TextMapGetter getter = - new TextMapGetter() { - @Override - public String get(HttpHeaders headers, String s) { - assert headers != null; - return headers.getHeaderString(s); - } - - @Override - public Iterable keys(HttpHeaders headers) { - List keys = new ArrayList<>(); - MultivaluedMap requestHeaders = headers.getRequestHeaders(); - requestHeaders.forEach((k, v) ->{ - keys.add(k); - }); - } -}; - -TextMapSetter setter = - new TextMapSetter() { - @Override - public void set(HttpURLConnection carrier, String key, String value) { - // Insert the context as Header - carrier.setRequestProperty(key, value); - } -}; - -//... -public void handle( HttpHeaders headers){ - Context extractedContext = opentelemetry.getPropagators().getTextMapPropagator() - .extract(Context.current(), headers, getter); - try (Scope scope = extractedContext.makeCurrent()) { - // Automatically use the extracted SpanContext as parent. - Span serverSpan = tracer.spanBuilder("GET /resource") - .setSpanKind(SpanKind.SERVER) - .startSpan(); - - try(Scope ignored = serverSpan.makeCurrent()) { - // Add the attributes defined in the Semantic Conventions - serverSpan.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); - serverSpan.setAttribute(SemanticAttributes.HTTP_SCHEME, "http"); - serverSpan.setAttribute(SemanticAttributes.HTTP_HOST, "localhost:8080"); - serverSpan.setAttribute(SemanticAttributes.HTTP_TARGET, "/resource"); - - HttpURLConnection transportLayer = (HttpURLConnection) url.openConnection(); - // Inject the request with the *current* Context, which contains our current Span. - openTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), transportLayer, setter); - // Make outgoing call - }finally { - serverSpan.end(); - } - } -} -``` - -## Metrics - -[Spans](/docs/concepts/signals/traces/#spans) provide detailed information about -your application, but produce data that is proportional to the load on the -system. In contrast, [metrics](/docs/concepts/signals/metrics) combine -individual measurements into aggregations, and produce data which is constant as -a function of system load. The aggregations lack details required to diagnose -low level issues, but complement spans by helping to identify trends and -providing application runtime telemetry. - -The metrics API defines a variety of instruments. Instruments record -measurements, which are aggregated by the metrics SDK and eventually exported -out of process. Instruments come in synchronous and asynchronous varieties. -Synchronous instruments record measurements as they happen. Asynchronous -instruments register a callback, which is invoked once per collection, and which -records measurements at that point in time. - -The following sections describe the OpenTelemetry Java metrics API. See -[SdkMeterProvider](../sdk/#sdkmeterprovider) for an overview of metrics SDK -concepts and configuration. - -### Acquiring a meter - -Anywhere in your application where you have manually instrumented code you can -call `opentelemetry.meterBuilder(instrumentationScopeName)` to get or create a -new meter instance using the builder pattern, or -`opentelemetry.getMeter(instrumentationScopeName)` to get or create a meter -based on just the instrument scope name. - -```java -// Get or create a named meter instance with instrumentation version using builder -Meter meter = openTelemetry.meterBuilder("dice-server") - .setInstrumentationVersion("0.1.0") - .build(); - -// Get or create a named meter instance by name only -Meter meter = openTelemetry.getMeter("dice-server"); -``` - -Now that you have [meters](/docs/concepts/signals/metrics/#meter) initialized. -you can create -[metric instruments](/docs/concepts/signals/metrics/#metric-instruments). - -### Acquiring a meter in Java agent - -If you are using the [Java agent], you can acquire a `Meter` from the global OpenTelemetry -instance: - -```java -import io.opentelemetry.api.GlobalOpenTelemetry; - -Meter meter = GlobalOpenTelemetry.getMeter("application"); -``` - -If you are using Spring Boot, you can add the following bean to your -`@SpringBootApplication` class - to acquire a `Meter` as in the -[Spring Boot starter](#acquiring-a-meter-in-spring-boot-starter) section below: - -```java -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.GlobalOpenTelemetry; - -@Configuration -public class OpenTelemetryConfig { - @Bean - public OpenTelemetry openTelemetry() { - return GlobalOpenTelemetry.get(); - } -} -``` - -### Acquiring a meter in Spring Boot starter - -If you are using the [Spring Boot starter], you can acquire a `Meter` from the -autowired OpenTelemetry instance: - -```java -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.metrics.Meter; - -@Controller -public class MyController { - private final Meter meter; - - public MyController(OpenTelemetry openTelemetry) { - this.meter = openTelemetry.getMeter("application"); - } -} -``` - -### Using Counters - -Counters can be used to measure non-negative, increasing values. - -```java -LongCounter counter = meter.counterBuilder("dice-lib.rolls.counter") - .setDescription("How many times the dice have been rolled.") - .setUnit("rolls") - .build(); - -counter.add(1, attributes); -``` - -### Using Observable (Async) Counters - -Observable counters can be used to measure an additive, non-negative, -monotonically increasing value. These counters specifically focus on the total -accumulated amount, which is gathered from external sources. Unlike synchronous -counters where each increment is recorded as it happens, observable counters -allow you to asynchronously monitor the overall sum of multiple increments. - -```java -ObservableLongCounter counter = meter.counterBuilder("dice-lib.uptime") - .buildWithCallback(measurement -> measurement.record(getUpTime())); -``` - -### Using UpDown Counters - -UpDown counters can increment and decrement, allowing you to observe a value -that goes up or down. - -```java -LongUpDownCounter counter = meter.upDownCounterBuilder("dice-lib.score") - .setDescription("Score from dice rolls.") - .setUnit("points") - .build(); - -//... - -counter.add(10, attributes); - -//... - -counter.add(-20, attributes); -``` - -### Using Observable (Async) UpDown Counters - -Observable UpDown counters can increment and decrement, allowing you to measure -an additive, non-negative, non-monotonically increasing cumulative value. These -UpDown counters specifically focus on the total accumulated amount, which is -gathered from external sources. Unlike synchronous UpDown counters where each -increment is recorded as it happens, observable counters allow you to -asynchronously monitor the overall sum of multiple increments. - -```java -ObservableDoubleUpDownCounter upDownCounter = meter.upDownCounterBuilder("dice-lib.score") - .buildWithCallback(measurement -> measurement.record(calculateScore())); -``` - -### Using Histograms - -Histograms are used to measure a distribution of values over time. - -```java -LongHistogram histogram = meter.histogramBuilder("dice-lib.rolls") - .ofLongs() // Required to get a LongHistogram, default is DoubleHistogram - .setDescription("A distribution of the value of the rolls.") - .setExplicitBucketBoundariesAdvice(Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L)) - .setUnit("points") - .build(); - -histogram.record(7, attributes); -``` - -### Using Observable (Async) Gauges - -Observable Gauges should be used to measure non-additive values. - -```java -ObservableDoubleGauge gauge = meter.gaugeBuilder("jvm.memory.used") - .buildWithCallback(measurement -> measurement.record(getMemoryUsed())); -``` - -### Adding Attributes - -When you generate metrics, adding attributes creates unique metric series based -on each distinct set of attributes that receive measurements. This leads to the -concept of 'cardinality', which is the total number of unique series. -Cardinality directly affects the size of the metric payloads that are exported. -Therefore, it's important to carefully select the dimensions included in these -attributes to prevent a surge in cardinality, often referred to as 'cardinality -explosion'. - -```java -Attributes attrs = Attributes.of( - stringKey("hostname"), "i-98c3d4938", - stringKey("region"), "us-east-1"); - -histogram.record(7, attrs); -``` - -## Logs - -Logs are distinct from metrics and traces in that **there is no user-facing -OpenTelemetry logs API**. Instead, there is tooling to bridge logs from existing -popular log frameworks (e.g. SLF4j, JUL, Logback, Log4j) into the OpenTelemetry -ecosystem. For rationale behind this design decision, see -[Logging specification](/docs/specs/otel/logs/). - -The two typical workflows discussed below each cater to different application -requirements. +When writing instrumentation, consult the semantic conventions and conform to +any which are applicable to the domain. + +OpenTelemetry Java [publishes artifacts](../api-components/#semantic-attributes) +to assist in conforming to the semantic conventions, including generated +constants for attribute keys and values. + +TODO: discuss instrumentation API and how it helps conform to semantic +conventions + +## Log instrumentation + +While the [LoggerProvider](../api-components/#loggerprovider) / +[Logger](../api-components/#logger) APIs are structurally similar to the +equivalent [trace](../api-components/#tracerprovider) and +[metric](../api-components/#meterprovider) APIs, they serve a different use +case. As of now, `LoggerProvider` / `Logger` and associated classes represent +the [Log Bridge API](/docs/specs/otel/logs/bridge-api/), which exists to write +log appenders to bridge logs recorded through other log APIs / frameworks into +OpenTelemetry. They are not intended for end user use as a replacement for Log4j +/ SLF4J / Logback / etc. + +There are two typical workflows for consuming log instrumentation in +OpenTelemetry catering to different application requirements: ### Direct to collector @@ -1104,47 +203,23 @@ In the direct to collector workflow, logs are emitted directly from an application to a collector using a network protocol (e.g. OTLP). This workflow is simple to set up as it doesn't require any additional log forwarding components, and allows an application to easily emit structured logs that -conform to the [log data model][log data model]. However, the overhead required -for applications to queue and export logs to a network location may not be -suitable for all applications. +conform to the [log data model](/docs/specs/otel/logs/data-model/). However, the +overhead required for applications to queue and export logs to a network +location may not be suitable for all applications. To use this workflow: -- Install appropriate [Log Appender](#log-appenders). +- Install appropriate log appender. **[1]** - Configure the OpenTelemetry [Log SDK](../sdk/#sdkloggerprovider) to export log records to desired target destination (the - [collector][opentelemetry collector] or other). - -#### Log appenders - -A log appender bridges logs from a log framework into the OpenTelemetry -[Log SDK](../sdk/#sdkloggerprovider) using the [Logs Bridge -API][logs bridge API]. Log appenders are available for various popular Java log -frameworks: - -- [Log4j2 Appender][log4j2 appender] -- [Logback Appender][logback appender] - -The links above contain full usage and installation documentation, but -installation is generally as follows: - -- Add required dependency via gradle or maven. -- Extend the application's log configuration (i.e. `logback.xml`, `log4j.xml`, - etc) to include a reference to the OpenTelemetry log appender. - - Optionally configure the log framework to determine which logs (i.e. filter - by severity or logger name) are passed to the appender. - - Optionally configure the appender to indicate how logs are mapped to - OpenTelemetry Log Records (i.e. capture thread information, context data, - markers, etc). - -Log appenders automatically include the trace context in log records, enabling -log correlation with traces. - -The [Log Appender example][log appender example] demonstrates setup for a -variety of scenarios. + [collector](https://github.com/open-telemetry/opentelemetry-collector) or + other). -See [SdkLoggerProvider](../sdk/#sdkloggerprovider) for an overview of log SDK -concepts and configuration. +**[1]**: Log appenders are a type of [shim](#shims) which bridges logs from a +log framework into the OpenTelemetry log SDK. See "Bridge Log4j into +OpenTelemetry", "Bridge Logback into OpenTelemetry" entries. See +[Log Appender example](https://github.com/open-telemetry/opentelemetry-java-docs/tree/main/log-appender) +for demonstration of a variety of scenarios. ### Via file or stdout @@ -1155,48 +230,11 @@ as the collector. This workflow may be preferable in situations where application requirements do not permit additional overhead from [direct to collector](#direct-to-collector). However, it requires that all log fields required down stream are encoded into the logs, and that the component -reading the logs parse the data into the [log data model][log data model]. The -installation and configuration of log forwarding components is outside the scope -of this document. - -Log correlation with traces is available by installing -[log context instrumentation](#log-context-instrumentation). - -#### Log context instrumentation - -OpenTelemetry provides components which enrich log context with trace context -for various popular Java log frameworks: - -- [Log4j context data instrumentation][log4j context instrumentation] -- [Logback MDC instrumentation][logback context instrumentation] - -This links above contain full usage and installation documentation, but -installation is generally as follows: - -- Add required dependency via gradle or maven. -- Extend the application's log configuration (i.e. `logback.xml` or `log4j.xml`, - etc) to reference the trace context fields in the log pattern. - -[httpexchange]: - https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpExchange.html -[java-vers]: - https://github.com/open-telemetry/opentelemetry-java/blob/main/VERSIONING.md#language-version-compatibility -[instrumentation library]: /docs/specs/otel/glossary/#instrumentation-library -[instrumented library]: /docs/specs/otel/glossary/#instrumented-library -[logs bridge API]: /docs/specs/otel/logs/bridge-api -[log data model]: /docs/specs/otel/logs/data-model -[log4j2 appender]: - https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/log4j/log4j-appender-2.17/library -[logback appender]: - https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/logback/logback-appender-1.0/library -[log appender example]: - https://github.com/open-telemetry/opentelemetry-java-docs/tree/main/log-appender -[log4j context instrumentation]: - https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure -[logback context instrumentation]: - https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/logback/logback-mdc-1.0/library -[obtaining a tracer]: /docs/specs/otel/trace/api/#get-a-tracer -[opentelemetry collector]: - https://github.com/open-telemetry/opentelemetry-collector -[Java agent]: /docs/zero-code/java/agent/ -[Spring Boot starter]: /docs/zero-code/java/spring-boot-starter/ +reading the logs parse the data into the +[log data model](/docs/specs/otel/logs/data-model). The installation and +configuration of log forwarding components is outside the scope of this +document. + +Log correlation with traces is available by installing a [shim](#shims) to +bridge OpenTelemetry context into the log framework. See "Bridge OpenTelemetry +context into Log4j", "Bridge OpenTelemetry context into Logback" entries. diff --git a/content/en/docs/languages/java/libraries.md b/content/en/docs/languages/java/libraries.md deleted file mode 100644 index e222378b2738..000000000000 --- a/content/en/docs/languages/java/libraries.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Using instrumentation libraries -linkTitle: Libraries -weight: 40 -cSpell:ignore: getenv httpclient println ---- - -{{% docs/languages/libraries-intro "java" %}} - -## Use Instrumentation Libraries - -If a library does not come with OpenTelemetry out of the box, you can use -[instrumentation libraries](/docs/specs/otel/glossary/#instrumentation-library) -in order to generate telemetry data for a library or framework. - -The Java agent for automatic instrumentation includes instrumentation libraries -for many common Java frameworks. Most are turned on by default. If you need to -turn off certain instrumentation libraries, you can -[suppress them](/docs/zero-code/java/agent/disable/). - -If you use [code-based instrumentation](../instrumentation), you can leverage -some instrumentation libraries for your dependencies standalone. To find out -which standalone instrumentation libraries are available, take a look at -[this list](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md#libraries--frameworks). -Follow the instructions of each instrumentation library to set them up. - -## Example app - -The following example instruments an HTTP client application using library -instrumentation which calls an HTTP server. - -You can use the dice example app as HTTP server from -[Getting Started](../getting-started/) or you can create your own HTTP server. - -### Dependencies - -Set up an environment in a new directory named `java-simple-http-client`. Inside -the directory, create a file named `build.gradle.kts` with the following -content: - -{{% alert title="Note" color="info" %}} The example is built using Gradle. You -might need to amend the directory structure and `pom.xml` to run using Maven. -{{% /alert %}} - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin -plugins { - id("java") - id("application") -} - -application { - mainClass.set("otel.SampleHttpClient") -} - -sourceSets { - main { - java.setSrcDirs(setOf(".")) - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation("io.opentelemetry:opentelemetry-api:{{% param vers.otel %}}"); - implementation("io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}"); - implementation("io.opentelemetry:opentelemetry-exporter-logging:{{% param vers.otel %}}"); - implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:{{% param vers.otel %}}"); - implementation("io.opentelemetry.instrumentation:opentelemetry-java-http-client:{{% param vers.instrumentation %}}-alpha"); -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - io.opentelemetry.instrumentation - opentelemetry-java-http-client - {{% param vers.instrumentation %}}-alpha - - -``` - -{{< /tab >}} {{< /tabpane>}} - -### Setup - -The following example shows how you can instrument external API calls using -[Java HTTP client library](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/java-http-client/library): - -```java -// SampleHttpClient.java -package otel; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.instrumentation.httpclient.JavaHttpClientTelemetry; -import java.net.http.HttpClient; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpHeaders; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -public final class SampleHttpClient { - //Init OpenTelemetry - private static final OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); - - //Use this HttpClient implementation for making standard http client calls. - public HttpClient createTracedClient(OpenTelemetry openTelemetry) { - return JavaHttpClientTelemetry.builder(openTelemetry).build().newHttpClient(createClient()); - } - - //your configuration of the Java HTTP Client goes here: - private HttpClient createClient() { - return HttpClient.newBuilder().build(); - } - - public static void main(String[] args) throws Exception { - HttpRequest request = HttpRequest.newBuilder() - .GET() - .uri(URI.create(System.getenv().getOrDefault("EXTERNAL_API_ENDPOINT", "http://localhost:8080/rolldice"))) - //.setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header - .build(); - - SampleHttpClient s = new SampleHttpClient(); - HttpResponse response = s.createTracedClient(openTelemetry).send(request, HttpResponse.BodyHandlers.ofString()); - // print response headers - HttpHeaders headers = response.headers(); - headers.map().forEach((k, v) -> System.out.println(k + ":" + v)); - // print status code - System.out.println(response.statusCode()); - // print response body - System.out.println(response.body()); - - } -} -``` - -### Run - -Set the `EXTERNAL_API_ENDPOINT` environment variable to specify the external API -endpoint. By default, it points to `http://localhost:8080/rolldice`, where -[example dice app](../getting-started/#example-application) is running. - -To check your code, run the app: - -```sh -env \ -OTEL_SERVICE_NAME=http-client \ -OTEL_TRACES_EXPORTER=logging \ -OTEL_METRICS_EXPORTER=logging \ -OTEL_LOGS_EXPORTER=logging \ -gradle run -``` - -When you run the app, the instrumentation libraries do the following: - -- Start a new trace. -- Generate a span that represents the request made to the external API endpoint. -- If you use an instrumented HTTP server, as in the - [dice app](../getting-started/#example-application), more trace spans are - generated with the same trace ID. - -## Available instrumentation libraries - -For a full list of instrumentation libraries, see -[opentelemetry-java-instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md#libraries--frameworks). - -## Next steps - -After you've set up instrumentation libraries, you might want to add -[additional instrumentation](../instrumentation) to collect custom telemetry -data. - -You might also want to [configure the SDK](../configuration/) to export to one -or more telemetry backends. - -For existing library instrumentations, also see -[Java agent](/docs/zero-code/java/agent/). - -[opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) diff --git a/content/en/docs/languages/java/sdk.md b/content/en/docs/languages/java/sdk.md index 11aa6f478ab5..f2c58896dbce 100644 --- a/content/en/docs/languages/java/sdk.md +++ b/content/en/docs/languages/java/sdk.md @@ -1,6 +1,6 @@ --- title: Manage Telemetry with SDK -weight: 11 +weight: 12 cSpell:ignore: autoconfigured FQCNs Interceptable Logback okhttp --- @@ -8,7 +8,7 @@ cSpell:ignore: autoconfigured FQCNs Interceptable Logback okhttp The SDK is the built-in reference implementation of the -[API](../instrumentation/), processing and exporting telemetry produced by +[API](../api-components/), processing and exporting telemetry produced by instrumentation API calls. This page is a conceptual overview of the SDK, including descriptions, links to relevant Javadocs, artifact coordinates, sample programmatic configurations and more. See @@ -55,6 +55,9 @@ implementing various plugin extension interfaces: ## SDK components +The `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` artifact +contains the OpenTelemetry SDK. + The following sections describe the core user-facing components of the SDK. Each component section includes: @@ -71,8 +74,7 @@ component section includes: ### OpenTelemetrySdk [OpenTelemetrySdk](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk/latest/io/opentelemetry/sdk/OpenTelemetrySdk.html) -is the SDK implementation of -[OpenTelemetry](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/OpenTelemetry.html). +is the SDK implementation of [OpenTelemetry](../api-components/#opentelemetry). It is a holder for top-level SDK components which makes it convenient to pass fully-configured SDK components to instrumentation. @@ -150,8 +152,8 @@ public class ResourceConfig { [SdkTracerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SdkTracerProvider.html) is the SDK implementation of -[TracerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/TracerProvider.html), -and is responsible for handling trace telemetry produced by the API. +[TracerProvider](../api-components/#tracerprovider), and is responsible for +handling trace telemetry produced by the API. `SdkTracerProvider` is configured by the application owner, and consists of: @@ -557,8 +559,7 @@ public class SpanLimitsConfig { ### SdkMeterProvider [SdkMeterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/SdkMeterProvider.html) -is the SDK implementation of -[MeterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/MeterProvider.html), +is the SDK implementation of [MeterProvider](../api-components/#meterprovider), and is responsible for handling metric telemetry produced by the API. `SdkMeterProvider` is configured by the application owner, and consists of: @@ -927,8 +928,8 @@ public class ViewConfig { [SdkLoggerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/SdkLoggerProvider.html) is the SDK implementation of -[LoggerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LoggerProvider.html), -and is responsible for handling log telemetry produced by the log bridge API. +[LoggerProvider](../api-components/#loggerprovider), and is responsible for +handling log telemetry produced by the log bridge API. `SdkLoggerProvider` is configured by the application owner, and consists of: @@ -1198,6 +1199,9 @@ public class LogLimitsConfig { is a [plugin extension interface](#sdk-plugin-extension-interfaces) responsible for propagating context across process boundaries in a text format. +TextMapPropagators built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + | Class | Artifact | Description | | --------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | `W3CTraceContextPropagator` | `io.opentelemetry:opentelemetry-api:{{% param vers.otel %}}` | Propagate trace context using W3C trace context propagation protocol. | diff --git a/layouts/partials/docs/native-libraries.md b/layouts/partials/docs/native-libraries.md new file mode 100644 index 000000000000..15f392695be0 --- /dev/null +++ b/layouts/partials/docs/native-libraries.md @@ -0,0 +1,31 @@ + +{{ $howMany := .Get 1 | default 10 -}} +{{ $langIndex := .Get 0 }} +{{ $lang := index $.Site.Data.instrumentation $langIndex -}} +{{ $integrations := where (slice ) ".language" $langIndex -}} + +{{ $integrations := slice }} {{ range $entry := $.Site.Data.registry }} +{{ if and (and (eq $entry.language $langIndex) (eq $entry.isNative true)) (eq $entry.registryType "instrumentation") }} +{{ $integrations = $integrations | append $entry }} {{ end }} {{ end }} + +{{ range first $howMany (sort $integrations "name") -}} + + +- [{{ .title }}]({{ .urls.docs }}) +{{- end }} + +{{ if eq (len $integrations) 0 -}} + + +{{ else -}} + +{{ end -}} diff --git a/layouts/shortcodes/docs/languages/libraries-intro.md b/layouts/shortcodes/docs/languages/libraries-intro.md index 00a40302dbe3..614e46f3ae41 100644 --- a/layouts/shortcodes/docs/languages/libraries-intro.md +++ b/layouts/shortcodes/docs/languages/libraries-intro.md @@ -31,24 +31,4 @@ OpenTelemetry SDK with your app. The library might require some additional configuration for the instrumentation. Go to the documentation for that library to learn more. -{{ range first $howMany (sort $integrations "name") -}} - - -- [{{ .title }}]({{ .urls.docs }}) -{{- end }} - -{{ if eq (len $integrations) 0 -}} - - -{{ else -}} - -{{ end -}} +{{ partial "docs/native-libraries.md" . }} diff --git a/layouts/shortcodes/docs/languages/native-libraries.md b/layouts/shortcodes/docs/languages/native-libraries.md new file mode 100644 index 000000000000..53f520730de3 --- /dev/null +++ b/layouts/shortcodes/docs/languages/native-libraries.md @@ -0,0 +1 @@ +{{ partial "docs/native-libraries.md" . }} diff --git a/static/refcache.json b/static/refcache.json index 9fc02794914b..d7639447eba3 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -3047,6 +3047,10 @@ "StatusCode": 200, "LastSeen": "2024-08-09T10:45:54.649845-04:00" }, + "https://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:17.488566-05:00" + }, "https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#availableProcessors--": { "StatusCode": 200, "LastSeen": "2024-01-30T16:04:00.071297-05:00" @@ -7519,6 +7523,10 @@ "StatusCode": 200, "LastSeen": "2024-01-30T06:06:25.505322-05:00" }, + "https://github.com/prometheus/client_java": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:19.363961-05:00" + }, "https://github.com/prometheus/prometheus/commit/d9d51c565c622cdc7d626d3e7569652bc28abe15#diff-bdaf80ebc5fa26365f45db53435b960ce623ea6f86747fb8870ad1abc355f64fR76-R83": { "StatusCode": 200, "LastSeen": "2024-01-18T19:37:11.409183-05:00" @@ -9019,6 +9027,14 @@ "StatusCode": 200, "LastSeen": "2024-08-09T10:43:55.405438-04:00" }, + "https://logback.qos.ch/": { + "StatusCode": 206, + "LastSeen": "2024-09-30T10:42:23.585047-05:00" + }, + "https://logging.apache.org/log4j/2.x/index.html": { + "StatusCode": 206, + "LastSeen": "2024-09-30T10:42:20.642504-05:00" + }, "https://lookerstudio.google.com/s/tSTKxK1ECeU": { "StatusCode": 200, "LastSeen": "2024-03-06T14:56:05.033361-05:00" @@ -10063,6 +10079,10 @@ "StatusCode": 206, "LastSeen": "2024-01-18T19:07:33.813401-05:00" }, + "https://opentracing.io/": { + "StatusCode": 206, + "LastSeen": "2024-09-30T10:42:13.94789-05:00" + }, "https://operatorhub.io/operator/opentelemetry-operator": { "StatusCode": 206, "LastSeen": "2024-01-18T19:10:45.627677-05:00" @@ -12923,22 +12943,134 @@ "StatusCode": 200, "LastSeen": "2024-01-18T19:55:46.525923-05:00" }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/GlobalOpenTelemetry.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:23.12239-05:00" + }, "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/OpenTelemetry.html": { "StatusCode": 200, "LastSeen": "2024-08-05T15:19:48.24217-05:00" }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/baggage/Baggage.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:43:07.738549-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/baggage/propagation/W3CBaggagePropagator.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:43:07.651421-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/common/Attributes.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:20.917364-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LogRecordBuilder.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:43:04.945711-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/Logger.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:43:01.318503-05:00" + }, "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LoggerProvider.html": { "StatusCode": 200, "LastSeen": "2024-08-05T15:59:36.584528-05:00" }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T11:26:12.546964-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleGauge.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:56.762156-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleHistogram.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:51.433911-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleUpDownCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:39.724087-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T11:26:11.401131-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongGauge.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:57.12662-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongHistogram.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:52.311487-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongUpDownCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:37.428847-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/Meter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:27.180222-05:00" + }, "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/MeterProvider.html": { "StatusCode": 200, "LastSeen": "2024-08-05T15:59:35.353354-05:00" }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableDoubleCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:35.879775-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableDoubleGauge.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:57.769016-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableDoubleUpDownCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:49.469015-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableLongCounter.htmll": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:34.290165-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableLongGauge.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:43:02.724791-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/ObservableLongUpDownCounter.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:45.458127-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/Span.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:25.46897-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/SpanBuilder.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:25.000171-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/Tracer.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:23.509988-05:00" + }, "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/TracerProvider.html": { "StatusCode": 200, "LastSeen": "2024-08-05T15:19:51.603241-05:00" }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/propagation/W3CTraceContextPropagator.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:26.645518-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/Context.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:14.126006-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/ContextStorage.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T11:26:04.981525-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/propagation/ContextPropagators.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:19.966187-05:00" + }, "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/propagation/TextMapPropagator.html": { "StatusCode": 200, "LastSeen": "2024-08-05T15:20:15.97313-05:00" @@ -13031,6 +13163,10 @@ "StatusCode": 200, "LastSeen": "2024-08-05T15:19:47.672179-05:00" }, + "https://www.javadoc.io/static/io.opentelemetry/opentelemetry-context/1.41.0/io/opentelemetry/context/ContextStorage.html": { + "StatusCode": 200, + "LastSeen": "2024-09-30T10:42:16.987832-05:00" + }, "https://www.jenkins.io": { "StatusCode": 206, "LastSeen": "2024-01-30T05:18:35.317496-05:00" From ebd44572139665fd0681b9aa0d3b61eaba31cd03 Mon Sep 17 00:00:00 2001 From: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Date: Fri, 18 Oct 2024 07:06:39 -0500 Subject: [PATCH 09/19] Update opentelemetry-java-instrumentation version to v2.9.0 (#5428) --- content/en/docs/languages/java/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/languages/java/_index.md b/content/en/docs/languages/java/_index.md index 36a40f27de57..65234d7132ae 100644 --- a/content/en/docs/languages/java/_index.md +++ b/content/en/docs/languages/java/_index.md @@ -6,7 +6,7 @@ description: >- aliases: [/java, /java/metrics, /java/tracing] cascade: vers: - instrumentation: 2.8.0 + instrumentation: 2.9.0 otel: 1.43.0 contrib: 1.38.0 semconv: 1.28.0 From b3bf36eff931aa832b4d3f61840bf7a98aeaf2e5 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 18 Oct 2024 08:14:52 -0400 Subject: [PATCH 10/19] [CI] Ensure spec processing works even if path contains a space (#5422) --- scripts/content-modules/adjust-pages.pl | 12 ++++++------ scripts/content-modules/cp-pages.sh | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/content-modules/adjust-pages.pl b/scripts/content-modules/adjust-pages.pl index c0d7fc219dc5..ae801b5728eb 100755 --- a/scripts/content-modules/adjust-pages.pl +++ b/scripts/content-modules/adjust-pages.pl @@ -127,15 +127,15 @@ () # Images s|(\.\./)?internal(/img/[-\w]+\.png)|$2|g; s|(\]\()(img/.*?\))|$1../$2|g if $ARGV !~ /(logs|schemas)._index/ && $ARGV !~ /otlp\/docs/; - s|(\]\()([^)]+\.png\))|$1../$2|g if $ARGV =~ /\/tmp\/semconv\/docs\/general\/attributes/; - s|(\]\()([^)]+\.png\))|$1../$2|g if $ARGV =~ /\/tmp\/semconv\/docs\/http\/http-spans/; + s|(\]\()([^)]+\.png\))|$1../$2|g if $ARGV =~ /\btmp\/semconv\/docs\/general\/attributes/; + s|(\]\()([^)]+\.png\))|$1../$2|g if $ARGV =~ /\btmp\/semconv\/docs\/http\/http-spans/; s|\.\.\/README.md\b|$otelSpecRepoUrl/|g if $ARGV =~ /specification._index/; s|\.\.\/README.md\b|..| if $ARGV =~ /specification.library-guidelines.md/; - s|\.\./(opentelemetry/proto/?.*)|$otlpSpecRepoUrl/tree/v$otlpSpecVers/$1|g if $ARGV =~ /\/tmp\/otlp/; - s|\.\./README.md\b|$otlpSpecRepoUrl/|g if $ARGV =~ /\/tmp\/otlp/; - s|\.\./examples/README.md\b|$otlpSpecRepoUrl/tree/v$otlpSpecVers/examples/|g if $ARGV =~ /\/tmp\/otlp/; + s|\.\./(opentelemetry/proto/?.*)|$otlpSpecRepoUrl/tree/v$otlpSpecVers/$1|g if $ARGV =~ /\btmp\/otlp/; + s|\.\./README.md\b|$otlpSpecRepoUrl/|g if $ARGV =~ /\btmp\/otlp/; + s|\.\./examples/README.md\b|$otlpSpecRepoUrl/tree/v$otlpSpecVers/examples/|g if $ARGV =~ /\btmp\/otlp/; s|\bREADME.md\b|_index.md|g if $ARGV !~ /otel\/specification\/protocol\/_index.md/; @@ -144,7 +144,7 @@ () s|(\.\.\/)+(supplementary-guidelines\/compatibility\/[^)]+)|$otelSpecRepoUrl/tree/v$otelSpecVers/$2|g; # Rewrite inline links - if ($ARGV =~ /\/tmp\/opamp/) { + if ($ARGV =~ /\btmp\/opamp/) { s|\]\(([^:\)]*?)\.md((#.*?)?)\)|]($1/$2)|g; } else { s|\]\(([^:\)]*?\.md(#.*?)?)\)|]({{% relref "$1" %}})|g; diff --git a/scripts/content-modules/cp-pages.sh b/scripts/content-modules/cp-pages.sh index a561afcf54a3..074d7652287b 100755 --- a/scripts/content-modules/cp-pages.sh +++ b/scripts/content-modules/cp-pages.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -SCRIPT_DIR="$(cd `dirname $0`; pwd)" -DEST_BASE="$(cd $SCRIPT_DIR; cd ../../; pwd)/tmp" +SCRIPT_DIR=$(dirname $0) +DEST_BASE=tmp ## OTel specification From 26b9decb5b09eaae85726cafd8133c8a4253ed69 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 18 Oct 2024 08:15:13 -0400 Subject: [PATCH 11/19] Update Docsy to v0.10.0-37-g7478e1a1 (#5435) --- .gitmodules | 2 +- themes/docsy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index ec8382827470..a222421c703b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "themes/docsy"] path = themes/docsy url = https://github.com/google/docsy.git - docsy-pin = v0.10.0-26-g79511949 + docsy-pin = v0.10.0-37-g7478e1a1 docsy-note = "2024-04-01 Switching to google/docsy.git from cncf/docsy.git since we don't have any CNCF customizations." docsy-reminder = "Ensure that any tag referenced by `docsy-pin` is present in the remote repo (url), otherwise add (push) the tags to the repo." [submodule "content-modules/opentelemetry-specification"] diff --git a/themes/docsy b/themes/docsy index 795119495470..7478e1a158da 160000 --- a/themes/docsy +++ b/themes/docsy @@ -1 +1 @@ -Subproject commit 7951194954708d7cc992e3540c8fc823cc99a953 +Subproject commit 7478e1a158dadbba35a1092883d1e7f16ef0f153 From a2fd8c4821848d266c28b731367ac3bd40992650 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 18 Oct 2024 09:01:21 -0400 Subject: [PATCH 12/19] OTel diagram: drop fill color in support of dark mode (#5436) --- static/img/otel-diagram.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/img/otel-diagram.svg b/static/img/otel-diagram.svg index 0bca7d5433b4..f7f198f4e4b3 100644 --- a/static/img/otel-diagram.svg +++ b/static/img/otel-diagram.svg @@ -1,6 +1,6 @@ - + From 418b15e9e71d6ab83e8592cbfab9a21423f92a47 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 18 Oct 2024 11:11:17 -0400 Subject: [PATCH 13/19] [infra] Update pkgs, Hugo to 0.136.1 (#5437) --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index ed05f392b032..7090bfc9f329 100644 --- a/package.json +++ b/package.json @@ -111,23 +111,23 @@ "update:submodule": "set -x && git submodule update --remote ${DEPTH:- --depth 999}" }, "devDependencies": { - "@cspell/dict-es-es": "^3.0.0", - "@cspell/dict-fr-fr": "^2.2.2", - "@cspell/dict-pt-br": "^2.3.0", + "@cspell/dict-es-es": "^3.0.3", + "@cspell/dict-fr-fr": "^2.2.5", + "@cspell/dict-pt-br": "^2.3.3", "ajv": "^8.17.1", "ajv-errors": "^3.0.0", "ajv-formats": "^3.0.1", "autoprefixer": "^10.4.20", - "cspell": "^8.14.4", + "cspell": "^8.15.4", "gulp": "^5.0.0", - "hugo-extended": "0.133.0", + "hugo-extended": "0.136.1", "js-yaml": "^4.1.0", "markdown-link-check": "^3.12.2", "markdownlint": "^0.35.0", "postcss-cli": "^11.0.0", "prettier": "^3.3.3", "require-dir": "^1.2.0", - "textlint": "^14.2.0", + "textlint": "^14.2.1", "textlint-filter-rule-allowlist": "^4.0.0", "textlint-filter-rule-comments": "^1.2.2", "textlint-rule-terminology": "^5.2.12", @@ -148,8 +148,8 @@ "path": "^0.12.7" }, "optionalDependencies": { - "netlify-cli": "^17.36.4", - "npm-check-updates": "^17.1.3" + "netlify-cli": "^17.37.1", + "npm-check-updates": "^17.1.4" }, "enginesComment": "Ensure that engines.node value stays consistent with the project's .nvmrc", "engines": { From 0823a19f07912749ec9b6f76596ab6cae2b81bd2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 19 Oct 2024 06:44:17 +0800 Subject: [PATCH 14/19] [zh] Add anchors and tweak lines in style-guide.md (#5430) Signed-off-by: windsonsea --- .htmltest.yml | 2 - content/zh/docs/contributing/style-guide.md | 58 +++++++++++++-------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/.htmltest.yml b/.htmltest.yml index 58774c8382e5..69135fd32180 100644 --- a/.htmltest.yml +++ b/.htmltest.yml @@ -8,8 +8,6 @@ CheckMailto: false TestFilesConcurrently: true IgnoreDirs: - ^blog/(\d+/)?page/\d+ - # TODO drop after https://github.com/open-telemetry/opentelemetry.io/issues/5267 is fixed: - - zh/docs/contributing/pr-checks # TODO drop after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed: - (ja|pt)/docs/concepts/instrumentation/libraries/ IgnoreInternalURLs: # list of paths diff --git a/content/zh/docs/contributing/style-guide.md b/content/zh/docs/contributing/style-guide.md index 24ad8a816096..c9800905d6cc 100644 --- a/content/zh/docs/contributing/style-guide.md +++ b/content/zh/docs/contributing/style-guide.md @@ -4,7 +4,7 @@ description: 编写 OpenTelemetry 文档时的术语和风格指南。 linkTitle: 风格指南 weight: 20 cSpell:ignore: open-telemetry postgre style-guide textlintrc -default_lang_commit: d78e63a +default_lang_commit: 2394fa1f1c693e547093e46e83a6819d3c26e9d5 --- OpenTelemetry 还没有官方的风格指南,当前版本的 OpenTelemetry 文档风格受到以下风格指南的启发: @@ -23,22 +23,24 @@ OpenTelemetry 还没有官方的风格指南,当前版本的 OpenTelemetry 文 {{% /alert %}} -## OpenTelemetry.io 单词列表 +## OpenTelemetry.io 单词列表 {#opentelemetryio-word-list} 请在整个网站上统一使用以下 OpenTelemetry 特定术语和词语列表。 -| Term | Usage | -| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| OpenTelemetry | OpenTelemetry 应始终大写。请勿使用 Open-Telemetry。 | -| OTel | OTel 是 OpenTelemetry 的公认缩写形式。请勿使用 OTEL。 | -| Collector | 当引用 OpenTelemetry Collector 时,请始终将 Collector 大写。在句子开头请使用 `The Collector` 或 `The Opentelemetry Collector`, 在句中或句尾则使用 `the Collector` 或 `the OpenTelemetry Collector`。如果您要将 Collector 用作形容词(例如, `Collector 配置` ),请只使用 `Collector` 。 | -| OTEP | OpenTelemetry 增强提案(OpenTelemetry Enhancement Proposal)。复数形式请写作 `OTEPs` 。请不要写成 `OTep` 或 `otep`。 | -| OpAMP | 开放代理管理协议(Open Agent Management Protocol)。请勿在描述或说明中写成 `OPAMP` 或 `opamp`。 | -| | | +| 术语 | 用法 | +| ---- | ----- | +| OpenTelemetry | OpenTelemetry 应始终大写。请勿使用 Open-Telemetry。| +| OTel | OTel 是 OpenTelemetry 的公认缩写形式。请勿使用 OTEL。| +| Collector | 当引用 OpenTelemetry Collector 时,请始终将 Collector 大写。在句子开头请使用 `The Collector` 或 `The Opentelemetry Collector`, 在句中或句尾则使用 `the Collector` 或 `the OpenTelemetry Collector`。如果您要将 Collector 用作形容词(例如, `Collector 配置` ),请只使用 `Collector`。| +| OTEP | OpenTelemetry 增强提案(OpenTelemetry Enhancement Proposal)。复数形式请写作 `OTEPs` 。请不要写成 `OTep` 或 `otep`。| +| OpAMP | 开放代理管理协议(Open Agent Management Protocol)。请勿在描述或说明中写成 `OPAMP` 或 `opamp`。| + -确保正确书写专有名词(例如其他 CNCF 项目或第三方工具)并使用原始大写字母。例如,书写 `PostgreSQL` 而不是 `postgre`。有关完整列表,请查看 [`.textlintrc.yml`](https://github.com/open-telemetry/opentelemetry.io/blob/main/.textlintrc.yml) 文件。 +确保正确书写专有名词(例如其他 CNCF 项目或第三方工具)并使用原始大写字母。例如, +书写 `PostgreSQL` 而不是 `postgre`。有关完整列表,请查看 +[`.textlintrc.yml`](https://github.com/open-telemetry/opentelemetry.io/blob/main/.textlintrc.yml) 文件。 另请参阅 [词汇表](/docs/concepts/glossary/) 以获取 OpenTelemetry术语及其定义的列表。 @@ -46,19 +48,27 @@ OpenTelemetry 还没有官方的风格指南,当前版本的 OpenTelemetry 文 运行 `npm run check:text -- --fix` 命令以修复书写不正确的术语和单词。 -## Markdown 标准 +## Markdown 标准 {#markdown-standards} -为了增强 Markdown 文件的标准性和一致性,所有文件都应遵循 [markdownlint](https://github.com/DavidAnson/markdownlint) 确定的相关规则。有关完整列表,请查看 [`.markdownlint.json`](https://github.com/open-telemetry/opentelemetry.io/blob/main/.markdownlint.json) 文件。 +为了增强 Markdown 文件的标准性和一致性,所有文件都应遵循 +[markdownlint](https://github.com/DavidAnson/markdownlint) +确定的相关规则。有关完整列表,请查看 +[`.markdownlint.json`](https://github.com/open-telemetry/opentelemetry.io/blob/main/.markdownlint.json) +文件。 运行 `npm run check:markdown` 命令以验证所有文件是否遵循标准。 运行 `npm run fix:markdown` 命令以修复与 Markdown 相关的格式问题。 -## 拼写检查 +## 拼写检查 {#spell-checking} -使用 [CSpell](https://github.com/streetsidesoftware/cspell) 确保所有文本拼写正确。有关 OpenTelemetry 网站特定单词的列表,请参阅 [`.cspell.yml`](https://github.com/open-telemetry/opentelemetry.io/blob/main/.cspell.yml) 文件。 +使用 [CSpell](https://github.com/streetsidesoftware/cspell) 确保所有文本拼写正确。 +有关 OpenTelemetry 网站特定单词的列表,请参阅 +[`.cspell.yml`](https://github.com/open-telemetry/opentelemetry.io/blob/main/.cspell.yml) 文件。 -运行 `npm run check:spelling` 命令以验证所有单词拼写是否正确。如果 `cspell` 指示 `Unknown word` 错误,请验证您是否正确编写了该单词。如果正确,请将此单词添加到文件顶部的 `cSpell:ignore` 部分。如果不存在这样的部分,您可以将其添加到 Markdown 文件的元数据中: +运行 `npm run check:spelling` 命令以验证所有单词拼写是否正确。如果 `cspell` 指示 +`Unknown word` 错误,请验证您是否正确编写了该单词。如果正确,请将此单词添加到文件顶部的 +`cSpell:ignore` 部分。如果不存在这样的部分,您可以将其添加到 Markdown 文件的元数据中: ```markdown --- @@ -67,19 +77,23 @@ cSpell:ignore: --- ``` -对于任何其他文件,请在适合文件上下文的注释行中添加 `cSpell:ignore `。对于 [registry](/ecosystem/registry/) 条目 YAML 文件,它可能看起来像这样: +对于任何其他文件,请在适合文件上下文的注释行中添加 `cSpell:ignore `。 +对于 [registry](/ecosystem/registry/) 条目 YAML 文件,它可能看起来像这样: ```yaml # cSpell:ignore title: registryEntryTitle ``` -网站工具通过移除重复单词、删除全局单词列表中的单词以及对单词进行排序来规范特定于页面的词典(即 `cSpell:ignore` 单词列表)。要规范特定于页面的词典,请运行 `npm run fix:dict`。 +网站工具通过移除重复单词、删除全局单词列表中的单词以及对单词进行排序来规范特定于页面的词典(即 +`cSpell:ignore` 单词列表)。要规范特定于页面的词典,请运行 `npm run fix:dict`。 -## 文件格式 +## 文件格式 {#file-format} -为了执行关于文件结构的特定标准,所有文件都应使用 [prettier](https://prettier.io) 进行格式化。在提交 PR 之前运行 `npm run fix:format`,或者在提交 PR 之后运行它并推送额外的提交。 +为了执行关于文件结构的特定标准,所有文件都应使用 [prettier](https://prettier.io) +进行格式化。在提交 PR 之前运行 `npm run fix:format`,或者在提交 PR 之后运行它并推送额外的提交。 -## 文件名 +## 文件名 {#file-names} -所有文件名都应采用[短横线命名](https://en.wikipedia.org/wiki/Letter_case#Kebab_case)。运行 `npm run fix:filenames` 以自动重命名文件。 +所有文件名都应采用[短横线命名](https://en.wikipedia.org/wiki/Letter_case#Kebab_case)。 +运行 `npm run fix:filenames` 以自动重命名文件。 From 277e52d5e74f2da0c4bbcf90f3f44e4d9f11d079 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 21 Oct 2024 05:21:05 -0400 Subject: [PATCH 15/19] Update docsy to 0.11.0 and Hugo to patch 0.136.2 (#5442) --- .gitmodules | 2 +- package.json | 2 +- themes/docsy | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index a222421c703b..896a8818601b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "themes/docsy"] path = themes/docsy url = https://github.com/google/docsy.git - docsy-pin = v0.10.0-37-g7478e1a1 + docsy-pin = v0.11.0 docsy-note = "2024-04-01 Switching to google/docsy.git from cncf/docsy.git since we don't have any CNCF customizations." docsy-reminder = "Ensure that any tag referenced by `docsy-pin` is present in the remote repo (url), otherwise add (push) the tags to the repo." [submodule "content-modules/opentelemetry-specification"] diff --git a/package.json b/package.json index 7090bfc9f329..5684f3fa47c1 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "autoprefixer": "^10.4.20", "cspell": "^8.15.4", "gulp": "^5.0.0", - "hugo-extended": "0.136.1", + "hugo-extended": "0.136.2", "js-yaml": "^4.1.0", "markdown-link-check": "^3.12.2", "markdownlint": "^0.35.0", diff --git a/themes/docsy b/themes/docsy index 7478e1a158da..cf0c68f041da 160000 --- a/themes/docsy +++ b/themes/docsy @@ -1 +1 @@ -Subproject commit 7478e1a158dadbba35a1092883d1e7f16ef0f153 +Subproject commit cf0c68f041daac066a0292d521461dbd092d7c31 From 65179dd7aa456de8f11190644cb5b6c6c9ab0ac5 Mon Sep 17 00:00:00 2001 From: arusevm <31587605+arusevm@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:29:53 +0300 Subject: [PATCH 16/19] Adding utility for Apache Druid ingestion of OTLP (#5427) Co-authored-by: Severin Neumann --- .../tools-java-druid-extension-otlp.yaml | 28 +++++++++++++++++++ static/refcache.json | 20 +++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 data/registry/tools-java-druid-extension-otlp.yaml diff --git a/data/registry/tools-java-druid-extension-otlp.yaml b/data/registry/tools-java-druid-extension-otlp.yaml new file mode 100644 index 000000000000..f0020a71f6ad --- /dev/null +++ b/data/registry/tools-java-druid-extension-otlp.yaml @@ -0,0 +1,28 @@ +title: Apache Druid extension for OTLP +registryType: utilities +language: java +tags: + - java + - druid + - utilities + - analytics + - dashboards + - monitoring +license: Apache 2.0 +description: This extension allows [Apache Druid](https://druid.apache.org/) to + ingest OpenTelemetry signals. + + An example setup would be to use the [Kafka + Exporter](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/kafkaexporter/README.md) + to publish OTLP data into Kafka topics, and then setup Druid ingestion jobs, + using this extension, to populate tables. +authors: + - name: mishmash io + email: opensourcemaintainers@mishmash.io + url: https://mishmash.io +urls: + repo: https://github.com/mishmash-io/opentelemetry-server-embedded + docs: https://github.com/mishmash-io/opentelemetry-server-embedded/tree/main/druid-otlp-format +createdAt: 2024-10-17 +isNative: false +isFirstParty: false diff --git a/static/refcache.json b/static/refcache.json index d7639447eba3..c29f78be943c 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -3335,6 +3335,10 @@ "StatusCode": 200, "LastSeen": "2024-01-30T15:24:54.677789-05:00" }, + "https://druid.apache.org/": { + "StatusCode": 206, + "LastSeen": "2024-10-18T16:50:18.107656338+03:00" + }, "https://dyladan.me/histograms/2023/05/02/why-histograms/": { "StatusCode": 206, "LastSeen": "2024-01-30T06:01:18.587594-05:00" @@ -5655,6 +5659,10 @@ "StatusCode": 200, "LastSeen": "2024-04-19T17:43:49.897716918Z" }, + "https://github.com/mishmash-io/opentelemetry-server-embedded": { + "StatusCode": 200, + "LastSeen": "2024-10-18T16:50:17.016614951+03:00" + }, "https://github.com/mjwolf": { "StatusCode": 200, "LastSeen": "2024-08-06T15:18:44.682117+02:00" @@ -9215,6 +9223,10 @@ "StatusCode": 206, "LastSeen": "2024-01-18T19:02:08.769984-05:00" }, + "https://mishmash.io": { + "StatusCode": 200, + "LastSeen": "2024-10-18T16:50:17.995881058+03:00" + }, "https://mobyproject.org/": { "StatusCode": 206, "LastSeen": "2024-08-07T15:43:31.13946+02:00" @@ -9931,6 +9943,10 @@ "StatusCode": 206, "LastSeen": "2024-02-23T22:55:04.014798-05:00" }, + "https://opentelemetry.io/docs/concepts/glossary/#instrumentation-library": { + "StatusCode": 206, + "LastSeen": "2024-10-18T16:49:48.155152358+03:00" + }, "https://opentelemetry.io/docs/concepts/instrumentation/libraries/": { "StatusCode": 206, "LastSeen": "2024-04-30T09:31:37.735092936Z" @@ -9975,6 +9991,10 @@ "StatusCode": 206, "LastSeen": "2024-09-04T09:48:32.91926+02:00" }, + "https://opentelemetry.io/docs/specs/otel/document-status": { + "StatusCode": 206, + "LastSeen": "2024-10-18T16:49:48.125677461+03:00" + }, "https://opentelemetry.io/docs/specs/otel/glossary/#instrumentation-library": { "StatusCode": 206, "LastSeen": "2024-04-30T09:31:37.929550219Z" From 0457368038be45cf5344063e98929f9cb4aec800 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 21 Oct 2024 11:35:50 -0400 Subject: [PATCH 17/19] [i18n, CI] How to deal with broken links in non-en pages when updating en pages (#5448) --- .cspell.yml | 2 + .htmltest.yml | 8 +- content/en/blog/_index.md | 6 +- content/en/docs/contributing/localization.md | 28 ++++ .../concepts/instrumentation/libraries.md | 4 + .../concepts/instrumentation/libraries.md | 4 + package.json | 9 +- scripts/htmltest-config.pl | 135 ++++++++++++++++++ scripts/htmltest-config.sh | 8 ++ 9 files changed, 196 insertions(+), 8 deletions(-) create mode 100755 scripts/htmltest-config.pl create mode 100755 scripts/htmltest-config.sh diff --git a/.cspell.yml b/.cspell.yml index 8e7b3da37da6..57d3c4fbc4f2 100644 --- a/.cspell.yml +++ b/.cspell.yml @@ -53,3 +53,5 @@ dictionaries: - softwareTerms # Other - companies +words: # Valid words across all locales + - htmltest diff --git a/.htmltest.yml b/.htmltest.yml index 69135fd32180..0d3a9386b8e2 100644 --- a/.htmltest.yml +++ b/.htmltest.yml @@ -7,9 +7,13 @@ IgnoreInternalEmptyHash: true # TODO: remove after resolution of https://github. CheckMailto: false TestFilesConcurrently: true IgnoreDirs: + # DO NOT EDIT! IgnoreDirs list is auto-generated from markdown file front matter. + # TODO drop next line after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed for ja pages: + - ^ja/docs/concepts/instrumentation/libraries/ + # TODO drop next line after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed for pt pages: + - ^pt/docs/concepts/instrumentation/libraries/ - ^blog/(\d+/)?page/\d+ - # TODO drop after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed: - - (ja|pt)/docs/concepts/instrumentation/libraries/ + # DO NOT EDIT! IgnoreDirs list is auto-generated from markdown file front matter. IgnoreInternalURLs: # list of paths IgnoreURLs: # list of regexs of paths or URLs to be ignored - ^/api$ diff --git a/content/en/blog/_index.md b/content/en/blog/_index.md index 022dd0feceae..7d0b3e2d57bf 100644 --- a/content/en/blog/_index.md +++ b/content/en/blog/_index.md @@ -1,7 +1,9 @@ --- title: Blog -menu: - main: { weight: 50 } +menu: { main: { weight: 50 } } redirects: [{ from: '', to: '2024/ 301!' }] outputs: [HTML, RSS] +htmltest: + IgnoreDirs: + - ^blog/(\d+/)?page/\d+ --- diff --git a/content/en/docs/contributing/localization.md b/content/en/docs/contributing/localization.md index f1a25fd11505..2d9d2e55673e 100644 --- a/content/en/docs/contributing/localization.md +++ b/content/en/docs/contributing/localization.md @@ -11,6 +11,34 @@ English is the default language, with US English as the default (implicit) local A growing number of other localizations are supported, as can be seen from the languages dropdown menu in the top nav. +## English language maintainer guidance + +### When link checking fails for non-English pages + +English is the default language of the OpenTelemetry website. After you add, +edit, or reorganized English language documentation, link checking may fail for +non-English pages. When this happens: + + + +- Do **not** fix the broken links. Each non-English page is associated with a + specific commit of the corresponding English page, as identified by the git + commit hash value of the `default_lang_commit` front matter key. +- Configure the link checker to ignore the non-English pages by adding the + following to the page's front matter, or to the closest common ancestor file, + when more than one page has link errors: + ```yaml + htmltest: + # TODO: remove the IgnoreDirs once broken links are fixed + IgnoreDirs: + - path-regex/to/non-en/directory/contain/files/to/ignore + - path-2-etc + ``` +- Run `npm run check:links` and include any updates to the `.htmltest.yml` + config file with your PR. + + + ## Translation guidance We recommend that you follow the guidance offered in this section when diff --git a/content/ja/docs/concepts/instrumentation/libraries.md b/content/ja/docs/concepts/instrumentation/libraries.md index e7c89111f324..38d1ed962104 100644 --- a/content/ja/docs/concepts/instrumentation/libraries.md +++ b/content/ja/docs/concepts/instrumentation/libraries.md @@ -3,6 +3,10 @@ title: ライブラリ description: ライブラリにネイティブ計装を追加する方法を紹介します。 weight: 40 default_lang_commit: d8c5612 +htmltest: + IgnoreDirs: + # TODO drop next line after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed for ja pages: + - ^ja/docs/concepts/instrumentation/libraries/ --- OpenTelemetryは、多くのライブラリに[計装ライブラリ][instrumentation libraries]を提供していて、これは通常、ライブラリフックやモンキーパッチライブラリコードを通して行われます。 diff --git a/content/pt/docs/concepts/instrumentation/libraries.md b/content/pt/docs/concepts/instrumentation/libraries.md index 3410ddd032f4..f9dd1e39938d 100644 --- a/content/pt/docs/concepts/instrumentation/libraries.md +++ b/content/pt/docs/concepts/instrumentation/libraries.md @@ -3,6 +3,10 @@ title: Bibliotecas description: Aprenda como adicionar instrumentação nativa à sua biblioteca. weight: 40 default_lang_commit: a570a00c7a238ffe26528d7bfb20efdbaf939c39 +htmltest: + IgnoreDirs: + # TODO drop next line after https://github.com/open-telemetry/opentelemetry.io/issues/5423 is fixed for pt pages: + - ^pt/docs/concepts/instrumentation/libraries/ --- O OpenTelemetry fornece [bibliotecas de instrumentação][] para várias diff --git a/package.json b/package.json index 5684f3fa47c1..0beecdac83d4 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,4 @@ { - "spelling": "cSpell:ignore docsy elemetry htmltest hugo loglevel netlify nowrap prebuild precheck preinstall postbuild postget refcache textlint -", "Notes": [ "The 'all' runs _all_ named scripts in sequence, even if one fails; and exits with failure in that case." ], @@ -86,8 +85,8 @@ "prebuild:preview": "npm run _prebuild", "prebuild:production": "npm run _prebuild", "prebuild": "npm run _prebuild", - "precheck:links:internal": "npm run build", - "precheck:links": "npm run build", + "precheck:links:internal": "npm run build && npm run update:htmltest-config", + "precheck:links": "npm run build && npm run update:htmltest-config", "prefix:submodules": "npm run update:submodule", "prenetlify-build:production": "echo 'IgnoreTagAttribute: rel' >> .htmltest.yml", "prepare": "npm run seq -- get:submodule _prepare:docsy", @@ -102,6 +101,7 @@ "test-and-fix": "npm run seq -- check fix:dict fix:filenames", "test": "npm run check", "update:docsy-dep": "npm install --save-dev autoprefixer@latest postcss-cli@latest", + "update:htmltest-config": "scripts/htmltest-config.sh", "update:hugo": "npm install --save-dev --save-exact hugo-extended@latest", "update:hugo+": "npm run update:hugo && npm run update:docsy-dep", "update:netlify": "npm install --save-optional netlify-cli@latest", @@ -160,5 +160,6 @@ "prettier": { "proseWrap": "always", "singleQuote": true - } + }, + "spelling": "cSpell:ignore docsy elemetry htmltest hugo loglevel netlify nowrap postnetlify prebuild precheck preinstall postbuild postget refcache textlint -" } diff --git a/scripts/htmltest-config.pl b/scripts/htmltest-config.pl new file mode 100755 index 000000000000..ebbf0d61a911 --- /dev/null +++ b/scripts/htmltest-config.pl @@ -0,0 +1,135 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my $gD = 0; + +sub main { + my @ignore_dirs; + + collect_htmltest_config_from_front_matter(\@ignore_dirs, @ARGV); + update_htmltest_config_file(\@ignore_dirs); +} + +sub collect_htmltest_config_from_front_matter { + my ($ignore_dirs_ref, @files) = @_; + + foreach my $file_path (@files) { + my @htmltest_config = extract_htmltest_config($file_path); + next unless @htmltest_config; + push @$ignore_dirs_ref, @htmltest_config; + } +} + +sub extract_htmltest_config { + # Returns list of htmlconfig lines extracted from the front matter of $file_path + my ($file_path) = @_; + + open my $fh, '<', $file_path or die "Could not open '$file_path': $!"; + my $content = do { local $/; <$fh> }; + close $fh; + + return unless $content =~ /---\n(.*?)\n---/s; + + my $front_matter = $1; + my @htmltest_config = _extract_htmltest_config($front_matter); + + return unless @htmltest_config; + + if (@htmltest_config == 1) { + warn "Warning: Failed to extract htmltest config from front matter in file '$file_path'.\n"; + return; + } + + shift @htmltest_config; + + if (@htmltest_config >= 1 && $htmltest_config[0] =~ /^IgnoreDirs:/i) { + return _extract_ignore_dirs($file_path, @htmltest_config) + } + + # TODO: Add support for `IgnoreURLs`. + + warn "Warning: Unrecognized htmltest config from front matter in file '$file_path'.\n"; +} + +sub _extract_ignore_dirs { + my ($file_path, + @ignore_dirs_config_lines # Can include comment lines + ) = @_; + my @config; + + foreach my $line (@ignore_dirs_config_lines) { + next if $line =~ /^IgnoreDirs:\s*$/i; + if ($line =~ /\s*#/) { + push @config, $line; + } elsif ($line =~ /^IgnoreDirs:\s*\[\s*(.*?)\s*\]/i || $line =~ /^\s*-\s*(.*?)$/) { + push @config, (split /\s*,\s*/, $1); + } else { + warn "Warning: Unrecognized htmltest IgnoreDirs config from front matter in file '$file_path': $line\n"; + } + } + return @config; +} + +sub _extract_htmltest_config { + # Returns a list of htmltext config lines with whitespace trimmed away. + + my ($front_matter) = @_; + my @lines = split /\n/, $front_matter; + my @htmltest_lines; + my $in_htmltest_section = 0; + + foreach my $line (@lines) { + if ($line =~ /^htmltest:(.*?)(#.*)?$/) { + $in_htmltest_section = 1; + push @htmltest_lines, $line; + } elsif ($in_htmltest_section) { + if ($line =~ /^(\s{2,})(.*)$/) { + push @htmltest_lines, $2; + printf " > Config line: $line" if $gD; + } else { + last; + } + } + } + return @htmltest_lines; +} + +sub update_htmltest_config_file { + my ($ignore_dirs_ref) = @_; + my $htmltest_config_path = '.htmltest.yml'; + my $do_not_edit_msg = " # DO NOT EDIT! IgnoreDirs list is auto-generated from markdown file front matter.\n"; + + # Read config file as array of lines + open my $fh, '<', $htmltest_config_path or die "Could not open '$htmltest_config_path' for reading: $!"; + my @lines = <$fh>; + close $fh; + + # Replace the existing IgnoreDirs entries with the new ones + my $in_ignore_dirs = 0; + my @new_lines; + foreach my $line (@lines) { + if ($line =~ /^IgnoreDirs:/) { + push @new_lines, ($line, $do_not_edit_msg); + foreach my $ignore_dir (@$ignore_dirs_ref) { + my $prefix = $ignore_dir =~ /^#/ ? ' ' : ' - '; + push @new_lines, "$prefix$ignore_dir\n"; + } + push @new_lines, $do_not_edit_msg; + $in_ignore_dirs = 1; + } elsif ($in_ignore_dirs) { + next if $line =~ /^\s*([#-]|$)/; + $in_ignore_dirs = 0; + push @new_lines, $line; + } else { + push @new_lines, $line; + } + } + + open my $fh_out, '>', $htmltest_config_path or die "Could not open '$htmltest_config_path' for writing: $!"; + print $fh_out @new_lines; + close $fh_out; +} + +main(); diff --git a/scripts/htmltest-config.sh b/scripts/htmltest-config.sh new file mode 100755 index 000000000000..02696c7c919c --- /dev/null +++ b/scripts/htmltest-config.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# +# We handle listing all markdown files here because it is more portable across +# supported operating systems. + +SCRIPT_DIR=$(dirname $0) +FILES=$(find content -name "*.md") +exec $SCRIPT_DIR/htmltest-config.pl $FILES From fc72093f2329e7675ca02f645e1fae52e621b40e Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 22 Oct 2024 10:10:28 +0200 Subject: [PATCH 18/19] zero-code/python: add django applications notes in operator doc (#5443) Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Phillip Carter --- content/en/docs/zero-code/python/operator.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/content/en/docs/zero-code/python/operator.md b/content/en/docs/zero-code/python/operator.md index 7675786a8563..9f5e6761b6dd 100644 --- a/content/en/docs/zero-code/python/operator.md +++ b/content/en/docs/zero-code/python/operator.md @@ -3,7 +3,8 @@ title: Using the OpenTelemetry Operator to Inject Auto-Instrumentation linkTitle: Operator aliases: [/docs/languages/python/automatic/operator] weight: 30 -cSpell:ignore: distro grpcio mkdir psutil uninstrumented virtualenv +# prettier-ignore +cSpell:ignore: distro grpcio mkdir myapp psutil PYTHONPATH uninstrumented virtualenv --- If you run your Python service in Kubernetes, you can take advantage of the @@ -26,3 +27,13 @@ specific Python version. The provides images for a single Python version based on the glibc C library. If you want to use it you might need to build your own image operator Docker image for Python auto-instrumentation. + +#### Django applications + +Applications that run from their own executable like Django requires to set in +your deployment file two environment variables: + +- `PYTHONPATH`, with the path to the Django application root directory, e.g. + "/app" +- `DJANGO_SETTINGS_MODULE`, with the name of the Django settings module, e.g. + "myapp.settings" From 4a8e68ba8755c41ff8ad3d6f5417c1f66849d9b6 Mon Sep 17 00:00:00 2001 From: Juliano Costa Date: Tue, 22 Oct 2024 13:23:08 +0200 Subject: [PATCH 19/19] Update feature-flags.md (#5444) --- content/en/docs/demo/feature-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/demo/feature-flags.md b/content/en/docs/demo/feature-flags.md index 4b9fd1c72999..71f9995131f5 100644 --- a/content/en/docs/demo/feature-flags.md +++ b/content/en/docs/demo/feature-flags.md @@ -18,7 +18,7 @@ change the `defaultVariant` value in the config file for a given flag to "on". | `adServiceFailure` | Ad Service | Generate an error for `GetAds` 1/10th of the time | | `adServiceManualGc` | Ad Service | Trigger full manual garbage collections in the ad service | | `adServiceHighCpu` | Ad Service | Trigger high cpu load in the ad service. If you want to demo cpu throttling, set cpu resource limits | -| `cartServiceFailure` | Cart Service | Generate an error for `EmptyCart` 1/10th of the time | +| `cartServiceFailure` | Cart Service | Generate an error whenever `EmptyCart` is called | | `productCatalogFailure` | Product Catalog | Generate an error for `GetProduct` requests with product ID: `OLJCESPC7Z` | | `recommendationServiceCacheFailure` | Recommendation | Create a memory leak due to an exponentially growing cache. 1.4x growth, 50% of requests trigger growth. | | `paymentServiceFailure` | Payment Service | Generate an error when calling the `charge` method. |