Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions semantic_conventions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,19 @@ These constants will be preserved to avoid breaking changes for users who rely
on the old constants. These constants do not differentiate between stable and
unstable constants. New constants will not be added to this namespace.

We recommend you require only the files that contain the constants you are going
to use. For example, if you were creating instrumentation for an HTTP Client
that emits only stable conventions, you would likely require:
Require the gem once and reference any constant directly. Each namespace is
registered with Ruby's `autoload`, so the file backing a namespace is only loaded
the first time you reference one of its constants — you don't pay to load
conventions you never use.

```rb
require 'opentelemetry/semconv/http'
require 'opentelemetry-semantic_conventions'

# Stable
OpenTelemetry::SemConv::HTTP::HTTP_REQUEST_METHOD # => 'http.request.method'

# Incubating (experimental/deprecated)
OpenTelemetry::SemConv::Incubating::GEN_AI::GEN_AI_SYSTEM
```

If you want to require all of the 1.11.0 constants, you can use:
Expand Down
44 changes: 43 additions & 1 deletion semantic_conventions/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ default_tasks =
task default: default_tasks

desc 'update semantic conventions'
task generate: %i[update_spec_version_constant generate_require_rollups]
task generate: %i[update_spec_version_constant generate_require_rollups generate_autoload_manifest]

SPEC_VERSION = '1.41.1'
OTEL_WEAVER_VERSION = 'v0.22.1'
Expand Down Expand Up @@ -122,6 +122,48 @@ task generate_require_rollups: %i[generate_semconv rubocop_autocorrect] do
end
end

# Render the autoload declarations for the given rollup files, indented for the
# manifest. The module constant is the screaming_snake_case of the namespace,
# which for these snake_case file names is just the upcased basename
# (e.g. gen_ai.rb => GEN_AI).
def semconv_autoloads(rollups, require_prefix, indent)
rollups.sort.map do |rollup|
namespace = rollup.basename('.rb').to_s
"#{' ' * indent}autoload :#{namespace.upcase}, '#{require_prefix}/#{namespace}'"
end.join("\n")
end

desc 'Generate the autoload manifest so a single require lazily exposes every namespace.'
task :generate_autoload_manifest do
puts "\n+++ Generating autoload manifest for the SemConv namespace.\n"

# The per-namespace rollup files sit directly under semconv_output_dir (stable)
# and under its incubating/ subdirectory.
stable = semconv_autoloads(semconv_output_dir.glob('*.rb'), 'opentelemetry/semconv', 4)
incubating = semconv_autoloads(semconv_output_dir.join('incubating').glob('*.rb'), 'opentelemetry/semconv/incubating', 6)

manifest_filename = semconv_output_dir.dirname + "#{semconv_output_dir.basename}.rb"
File.write(manifest_filename, <<~MANIFEST)
# frozen_string_literal: true

#{COPYRIGHT_NOTICE}
# This file was autogenerated. Do not edit it by hand.

module OpenTelemetry
# Stable OpenTelemetry semantic convention constants, autoloaded per namespace.
module SemConv
#{stable}

# Experimental, development, or deprecated semantic convention constants.
module Incubating
#{incubating}
end
end
end
MANIFEST
puts "✅ Generated file \"#{manifest_filename}\""
end

desc 'Bump the semantic_conventions gem version to match the spec'
task :update_spec_version_constant do
puts "\n+++ Updating library SPEC_VERSION constant to #{SPEC_VERSION}.\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
# SPDX-License-Identifier: Apache-2.0

require_relative 'opentelemetry/semantic_conventions'
require_relative 'opentelemetry/semconv'
139 changes: 139 additions & 0 deletions semantic_conventions/lib/opentelemetry/semconv.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# This file was autogenerated. Do not edit it by hand.

module OpenTelemetry
# Stable OpenTelemetry semantic convention constants, autoloaded per namespace.
module SemConv
autoload :ASPNETCORE, 'opentelemetry/semconv/aspnetcore'
autoload :CLIENT, 'opentelemetry/semconv/client'
autoload :CODE, 'opentelemetry/semconv/code'
autoload :DB, 'opentelemetry/semconv/db'
autoload :DEPLOYMENT, 'opentelemetry/semconv/deployment'
autoload :DOTNET, 'opentelemetry/semconv/dotnet'
autoload :ERROR, 'opentelemetry/semconv/error'
autoload :EXCEPTION, 'opentelemetry/semconv/exception'
autoload :HTTP, 'opentelemetry/semconv/http'
autoload :JVM, 'opentelemetry/semconv/jvm'
autoload :KESTREL, 'opentelemetry/semconv/kestrel'
autoload :NETWORK, 'opentelemetry/semconv/network'
autoload :OTEL, 'opentelemetry/semconv/otel'
autoload :SERVER, 'opentelemetry/semconv/server'
autoload :SERVICE, 'opentelemetry/semconv/service'
autoload :SIGNALR, 'opentelemetry/semconv/signalr'
autoload :TELEMETRY, 'opentelemetry/semconv/telemetry'
autoload :URL, 'opentelemetry/semconv/url'
autoload :USER_AGENT, 'opentelemetry/semconv/user_agent'

# Experimental, development, or deprecated semantic convention constants.
module Incubating
autoload :ANDROID, 'opentelemetry/semconv/incubating/android'
autoload :APP, 'opentelemetry/semconv/incubating/app'
autoload :ARTIFACT, 'opentelemetry/semconv/incubating/artifact'
autoload :ASPNETCORE, 'opentelemetry/semconv/incubating/aspnetcore'
autoload :AWS, 'opentelemetry/semconv/incubating/aws'
autoload :AZ, 'opentelemetry/semconv/incubating/az'
autoload :AZURE, 'opentelemetry/semconv/incubating/azure'
autoload :BROWSER, 'opentelemetry/semconv/incubating/browser'
autoload :CASSANDRA, 'opentelemetry/semconv/incubating/cassandra'
autoload :CICD, 'opentelemetry/semconv/incubating/cicd'
autoload :CLIENT, 'opentelemetry/semconv/incubating/client'
autoload :CLOUD, 'opentelemetry/semconv/incubating/cloud'
autoload :CLOUDEVENTS, 'opentelemetry/semconv/incubating/cloudevents'
autoload :CLOUDFOUNDRY, 'opentelemetry/semconv/incubating/cloudfoundry'
autoload :CODE, 'opentelemetry/semconv/incubating/code'
autoload :CONTAINER, 'opentelemetry/semconv/incubating/container'
autoload :CPU, 'opentelemetry/semconv/incubating/cpu'
autoload :CPYTHON, 'opentelemetry/semconv/incubating/cpython'
autoload :DB, 'opentelemetry/semconv/incubating/db'
autoload :DEPLOYMENT, 'opentelemetry/semconv/incubating/deployment'
autoload :DESTINATION, 'opentelemetry/semconv/incubating/destination'
autoload :DEVICE, 'opentelemetry/semconv/incubating/device'
autoload :DISK, 'opentelemetry/semconv/incubating/disk'
autoload :DNS, 'opentelemetry/semconv/incubating/dns'
autoload :DOTNET, 'opentelemetry/semconv/incubating/dotnet'
autoload :ELASTICSEARCH, 'opentelemetry/semconv/incubating/elasticsearch'
autoload :ENDUSER, 'opentelemetry/semconv/incubating/enduser'
autoload :ERROR, 'opentelemetry/semconv/incubating/error'
autoload :EVENT, 'opentelemetry/semconv/incubating/event'
autoload :EXCEPTION, 'opentelemetry/semconv/incubating/exception'
autoload :FAAS, 'opentelemetry/semconv/incubating/faas'
autoload :FEATURE_FLAG, 'opentelemetry/semconv/incubating/feature_flag'
autoload :FILE, 'opentelemetry/semconv/incubating/file'
autoload :GCP, 'opentelemetry/semconv/incubating/gcp'
autoload :GEN_AI, 'opentelemetry/semconv/incubating/gen_ai'
autoload :GEO, 'opentelemetry/semconv/incubating/geo'
autoload :GO, 'opentelemetry/semconv/incubating/go'
autoload :GRAPHQL, 'opentelemetry/semconv/incubating/graphql'
autoload :HEROKU, 'opentelemetry/semconv/incubating/heroku'
autoload :HOST, 'opentelemetry/semconv/incubating/host'
autoload :HTTP, 'opentelemetry/semconv/incubating/http'
autoload :HW, 'opentelemetry/semconv/incubating/hw'
autoload :IOS, 'opentelemetry/semconv/incubating/ios'
autoload :JSONRPC, 'opentelemetry/semconv/incubating/jsonrpc'
autoload :JVM, 'opentelemetry/semconv/incubating/jvm'
autoload :K8S, 'opentelemetry/semconv/incubating/k8s'
autoload :KESTREL, 'opentelemetry/semconv/incubating/kestrel'
autoload :LINUX, 'opentelemetry/semconv/incubating/linux'
autoload :LOG, 'opentelemetry/semconv/incubating/log'
autoload :MAINFRAME, 'opentelemetry/semconv/incubating/mainframe'
autoload :MCP, 'opentelemetry/semconv/incubating/mcp'
autoload :MESSAGE, 'opentelemetry/semconv/incubating/message'
autoload :MESSAGING, 'opentelemetry/semconv/incubating/messaging'
autoload :NET, 'opentelemetry/semconv/incubating/net'
autoload :NETWORK, 'opentelemetry/semconv/incubating/network'
autoload :NFS, 'opentelemetry/semconv/incubating/nfs'
autoload :NODEJS, 'opentelemetry/semconv/incubating/nodejs'
autoload :OCI, 'opentelemetry/semconv/incubating/oci'
autoload :ONC_RPC, 'opentelemetry/semconv/incubating/onc_rpc'
autoload :OPENAI, 'opentelemetry/semconv/incubating/openai'
autoload :OPENSHIFT, 'opentelemetry/semconv/incubating/openshift'
autoload :OPENTRACING, 'opentelemetry/semconv/incubating/opentracing'
autoload :ORACLE, 'opentelemetry/semconv/incubating/oracle'
autoload :ORACLE_CLOUD, 'opentelemetry/semconv/incubating/oracle_cloud'
autoload :OS, 'opentelemetry/semconv/incubating/os'
autoload :OTEL, 'opentelemetry/semconv/incubating/otel'
autoload :OTHER, 'opentelemetry/semconv/incubating/other'
autoload :PEER, 'opentelemetry/semconv/incubating/peer'
autoload :POOL, 'opentelemetry/semconv/incubating/pool'
autoload :PPROF, 'opentelemetry/semconv/incubating/pprof'
autoload :PROCESS, 'opentelemetry/semconv/incubating/process'
autoload :PROFILE, 'opentelemetry/semconv/incubating/profile'
autoload :RPC, 'opentelemetry/semconv/incubating/rpc'
autoload :SECURITY_RULE, 'opentelemetry/semconv/incubating/security_rule'
autoload :SERVER, 'opentelemetry/semconv/incubating/server'
autoload :SERVICE, 'opentelemetry/semconv/incubating/service'
autoload :SESSION, 'opentelemetry/semconv/incubating/session'
autoload :SIGNALR, 'opentelemetry/semconv/incubating/signalr'
autoload :SOURCE, 'opentelemetry/semconv/incubating/source'
autoload :SYSTEM, 'opentelemetry/semconv/incubating/system'
autoload :TELEMETRY, 'opentelemetry/semconv/incubating/telemetry'
autoload :TEST, 'opentelemetry/semconv/incubating/test'
autoload :THREAD, 'opentelemetry/semconv/incubating/thread'
autoload :TLS, 'opentelemetry/semconv/incubating/tls'
autoload :URL, 'opentelemetry/semconv/incubating/url'
autoload :USER, 'opentelemetry/semconv/incubating/user'
autoload :USER_AGENT, 'opentelemetry/semconv/incubating/user_agent'
autoload :V8JS, 'opentelemetry/semconv/incubating/v8js'
autoload :VCS, 'opentelemetry/semconv/incubating/vcs'
autoload :WEBENGINE, 'opentelemetry/semconv/incubating/webengine'
autoload :ZOS, 'opentelemetry/semconv/incubating/zos'
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require 'test_helper'

# test_helper eager-requires every file, which would mask autoload, so the
# lazy-loading behaviour is exercised in a clean subprocess.
describe 'OpenTelemetry::SemConv autoload' do
let(:gem_root) { File.expand_path('../../..', __dir__) }

it 'lazily exposes stable and incubating namespaces from a single require' do
script = <<~RUBY
require 'opentelemetry-semantic_conventions'
raise 'stable namespace not autoloaded' unless OpenTelemetry::SemConv::HTTP::HTTP_REQUEST_METHOD == 'http.request.method'
raise 'incubating namespace not autoloaded' unless OpenTelemetry::SemConv::Incubating::GEN_AI::GEN_AI_SYSTEM == 'gen_ai.system'
RUBY

lib = File.join(gem_root, 'lib')
api_lib = File.expand_path('../api/lib', gem_root)
ok = system(Gem.ruby, "-I#{lib}", "-I#{api_lib}", '-e', script)

assert ok, 'a single require should lazily load both stable and incubating constants'
end

it 'registers an autoload for every generated namespace rollup' do
manifest = File.read(File.join(gem_root, 'lib', 'opentelemetry', 'semconv.rb'))

namespaces_in('*.rb').each do |ns|
assert_includes manifest, "autoload :#{ns.upcase}, 'opentelemetry/semconv/#{ns}'"
end

namespaces_in('incubating', '*.rb').each do |ns|
assert_includes manifest, "autoload :#{ns.upcase}, 'opentelemetry/semconv/incubating/#{ns}'"
end
end

private

# Namespace basenames of the rollup files matched by +glob+ under the semconv dir.
def namespaces_in(*glob)
Dir[File.join(gem_root, 'lib', 'opentelemetry', 'semconv', *glob)].map { |f| File.basename(f, '.rb') }
end
end