mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-11-06 05:17:08 +00:00
Bump otel to v1.47.0
See https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.47.0 and https://github.com/open-telemetry/opentelemetry-go-contrib/releases/tag/v1.47.0 for details. Signed-off-by: Stephen Kitt <skitt@redhat.com>
This commit is contained in:
106 files changed
+3936
-766
No files matched your search
+234
@@ -0,0 +1,234 @@
|
||||
= vendor/go.opentelemetry.io/otel/log licensed under: =
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
= vendor/go.opentelemetry.io/otel/LICENSE 24dad3abbe7a8f390afc8ab967bfefa7
|
||||
@@ -58,13 +58,13 @@ require (
|
||||
go.etcd.io/etcd/api/v3 v3.7.2
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2
|
||||
go.etcd.io/etcd/client/v3 v3.7.2
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.71.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.72.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0
|
||||
go.opentelemetry.io/otel v1.47.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0
|
||||
go.opentelemetry.io/otel/metric v1.46.0
|
||||
go.opentelemetry.io/otel/sdk v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
go.opentelemetry.io/otel/metric v1.47.0
|
||||
go.opentelemetry.io/otel/sdk v1.47.0
|
||||
go.opentelemetry.io/otel/trace v1.47.0
|
||||
go.opentelemetry.io/proto/otlp v1.11.0
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.uber.org/zap v1.27.1
|
||||
@@ -78,7 +78,7 @@ require (
|
||||
golang.org/x/text v0.42.0
|
||||
golang.org/x/time v0.16.0
|
||||
golang.org/x/tools v0.50.0
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc
|
||||
google.golang.org/grpc v1.84.0
|
||||
google.golang.org/protobuf v1.36.12
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0
|
||||
@@ -198,8 +198,9 @@ require (
|
||||
go.etcd.io/etcd/server/v3 v3.7.2 // indirect
|
||||
go.etcd.io/raft/v3 v3.7.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba // indirect
|
||||
|
||||
@@ -342,30 +342,32 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.71.0 h1:xQ4gMo9rPMvy/e6YsAtTNEV5UY1qea1GCpVxFPbCZZU=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.71.0/go.mod h1:/1WbdEdBZgvzX8k1dvRbXvlOt9/+qA0eDMNHzh+MV1w=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.46.0 h1:OFVqWObn7xLIbOjE/koO0LS9fZJNgAyBD0msA+UQAoc=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.46.0/go.mod h1:t/d64xy7xuuEDJN/4ThqohLgRhIuQxL9y7P1v02bYuM=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.72.0 h1:ebYshGLa7IWUX0+Ph3Uva2WBg/k7qBiqXuZ//+dYPcs=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.72.0/go.mod h1:Omwcf+Xoh/bdLf83ty4Qr0OS7d0hby0s8qUGkDxnTxM=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.47.0 h1:vlKDmtjhe1R0d7kdov/+KVTKWOKeGLyohB+iXoDPRMQ=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.47.0/go.mod h1:0zRiXIfXU30PKYMsdbqYbGK8iHF8KqyPi0qdXT2wAuE=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.46.0 h1:KdRxPiAoMptR3vfWzvjjvutTsSiwbC2uG0496rzZNfo=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.46.0/go.mod h1:K/qSA+3G7Eovxi4K09wzrAgkWRnosS0DAOZeEpve7sM=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.47.0 h1:N3YQCxjxQ/bMjyc3heladfRm9t9RTksGQH8z4w6yU/0=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.47.0/go.mod h1:Mp8HOFqcaUyypCuGv9IhDdTHnJ56lSudSHMd+pVSCEA=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -449,8 +451,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -20,8 +20,8 @@ require (
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.70.0 // indirect
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
k8s.io/apimachinery v0.0.0 // indirect
|
||||
|
||||
@@ -26,10 +26,10 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
||||
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
|
||||
@@ -18,8 +18,8 @@ require (
|
||||
github.com/stretchr/testify v1.12.1
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2
|
||||
go.etcd.io/etcd/client/v3 v3.7.2
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
go.opentelemetry.io/otel v1.47.0
|
||||
go.opentelemetry.io/otel/trace v1.47.0
|
||||
go.yaml.in/yaml/v2 v2.4.4
|
||||
golang.org/x/sync v0.23.0
|
||||
golang.org/x/text v0.42.0
|
||||
@@ -90,12 +90,13 @@ require (
|
||||
go.etcd.io/etcd/server/v3 v3.7.2 // indirect
|
||||
go.etcd.io/raft/v3 v3.7.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
@@ -110,7 +111,7 @@ require (
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
golang.org/x/tools v0.50.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
|
||||
+20
-18
@@ -192,24 +192,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -273,8 +275,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -29,13 +29,13 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2
|
||||
go.etcd.io/etcd/client/v3 v3.7.2
|
||||
go.etcd.io/etcd/server/v3 v3.7.2
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0
|
||||
go.opentelemetry.io/otel v1.47.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0
|
||||
go.opentelemetry.io/otel/metric v1.46.0
|
||||
go.opentelemetry.io/otel/sdk v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
go.opentelemetry.io/otel/metric v1.47.0
|
||||
go.opentelemetry.io/otel/sdk v1.47.0
|
||||
go.opentelemetry.io/otel/trace v1.47.0
|
||||
go.uber.org/zap v1.27.1
|
||||
golang.org/x/crypto v0.57.0
|
||||
golang.org/x/net v0.59.0
|
||||
@@ -105,7 +105,8 @@ require (
|
||||
go.etcd.io/etcd/pkg/v3 v3.7.2 // indirect
|
||||
go.etcd.io/raft/v3 v3.7.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
@@ -113,7 +114,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba // indirect
|
||||
golang.org/x/oauth2 v0.37.0 // indirect
|
||||
golang.org/x/term v0.46.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
)
|
||||
|
||||
|
||||
Generated
+20
-18
@@ -192,24 +192,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -268,8 +270,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -69,14 +69,15 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.7.2 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
@@ -91,7 +92,7 @@ require (
|
||||
golang.org/x/term v0.46.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
|
||||
Generated
+20
-18
@@ -181,24 +181,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -240,8 +242,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -19,11 +19,11 @@ require (
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/stretchr/testify v1.12.1
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0
|
||||
go.opentelemetry.io/otel v1.47.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0
|
||||
go.opentelemetry.io/otel/sdk v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
go.opentelemetry.io/otel/sdk v1.47.0
|
||||
go.opentelemetry.io/otel/trace v1.47.0
|
||||
go.uber.org/zap v1.27.1
|
||||
go.yaml.in/yaml/v2 v2.4.4
|
||||
golang.org/x/sys v0.48.0
|
||||
@@ -60,8 +60,9 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
@@ -70,7 +71,7 @@ require (
|
||||
golang.org/x/term v0.46.0 // indirect
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
|
||||
Generated
+18
-16
@@ -126,22 +126,24 @@ github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtX
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -179,8 +181,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -63,14 +63,15 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.7.2 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
@@ -85,7 +86,7 @@ require (
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
|
||||
+20
-18
@@ -177,24 +177,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -235,8 +237,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -15,5 +15,5 @@ require (
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
)
|
||||
Generated
+2
-2
@@ -47,8 +47,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260706201446-f0a921348800/go.mod h1:FPk7EXUKMtImne7AmknoYjT4QXqKIzzRbeQIXzLk6fQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -10,10 +10,10 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.2
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/stretchr/testify v1.12.1
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/otel/sdk v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0
|
||||
go.opentelemetry.io/otel v1.47.0
|
||||
go.opentelemetry.io/otel/sdk v1.47.0
|
||||
go.opentelemetry.io/otel/trace v1.47.0
|
||||
golang.org/x/sys v0.48.0
|
||||
google.golang.org/grpc v1.84.0
|
||||
google.golang.org/protobuf v1.36.12
|
||||
@@ -29,11 +29,12 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
|
||||
Generated
+18
-16
@@ -69,21 +69,23 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
@@ -109,8 +111,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -24,7 +24,7 @@ require (
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
k8s.io/utils v0.0.0-20260626114624-be93311217bd // indirect
|
||||
)
|
||||
|
||||
Generated
+2
-2
@@ -66,8 +66,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260706201446-f0a921348800/go.mod h1:FPk7EXUKMtImne7AmknoYjT4QXqKIzzRbeQIXzLk6fQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -54,8 +54,8 @@ require (
|
||||
github.com/spf13/cobra v1.10.2 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
@@ -69,7 +69,7 @@ require (
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
||||
+12
-11
@@ -140,17 +140,18 @@ go.etcd.io/etcd/server/v3 v3.7.2/go.mod h1:tlvKX6r/kTEqRV9mydK2qzgI4WcojFEHKHHsZ
|
||||
go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
@@ -189,8 +190,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -42,8 +42,8 @@ require (
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
|
||||
Generated
+10
-9
@@ -88,15 +88,16 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
@@ -125,7 +126,7 @@ golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo
|
||||
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
|
||||
@@ -15,5 +15,5 @@ require (
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
)
|
||||
Generated
+2
-2
@@ -47,8 +47,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260706201446-f0a921348800/go.mod h1:FPk7EXUKMtImne7AmknoYjT4QXqKIzzRbeQIXzLk6fQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -15,5 +15,5 @@ require (
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
)
|
||||
Generated
+2
-2
@@ -47,8 +47,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260706201446-f0a921348800/go.mod h1:FPk7EXUKMtImne7AmknoYjT4QXqKIzzRbeQIXzLk6fQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -16,7 +16,7 @@ require (
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
)
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
|
||||
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -12,9 +12,9 @@ require (
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/stretchr/testify v1.12.1
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/otel/sdk v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
go.opentelemetry.io/otel v1.47.0
|
||||
go.opentelemetry.io/otel/sdk v1.47.0
|
||||
go.opentelemetry.io/otel/trace v1.47.0
|
||||
golang.org/x/net v0.59.0
|
||||
k8s.io/api v0.0.0
|
||||
k8s.io/apimachinery v0.0.0
|
||||
@@ -75,11 +75,12 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.7.2 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
@@ -96,7 +97,7 @@ require (
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
golang.org/x/tools v0.50.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
|
||||
+20
-18
@@ -182,24 +182,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -245,8 +247,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
+9
-8
@@ -57,14 +57,15 @@ go.etcd.io/etcd/api/v3 v3.7.2/go.mod h1:RoRCBRt9BfBff1pIGZLUVMiz7wu3bY+b2qLysGu1
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2/go.mod h1:HsSux/B3ahgyw/D5+d4YbZqicOi0mEbuxm6lIUdjAoI=
|
||||
go.etcd.io/etcd/client/v3 v3.7.2/go.mod h1:x03t1qMs4tGZirCDJlMuzPBJdQffXJImIyEjLhNBCsY=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
@@ -86,7 +87,7 @@ golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
|
||||
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
|
||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
|
||||
Generated
+10
-9
@@ -58,15 +58,16 @@ github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUm
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
@@ -89,7 +90,7 @@ golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
|
||||
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
|
||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
|
||||
Generated
+8
-7
@@ -73,13 +73,14 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2/go.mod h1:HsSux/B3ahgyw/D5+d4YbZqicOi0mEbuxm6lIUdjAoI=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
@@ -109,7 +110,7 @@ golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo
|
||||
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
|
||||
Generated
+8
-7
@@ -165,13 +165,14 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
@@ -206,7 +207,7 @@ golang.org/x/tools v0.50.0/go.mod h1:7ulVMw3831Mwi5EZD6RomGyffr4VFjuNYXf2BbCEAV0
|
||||
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
|
||||
@@ -30,7 +30,7 @@ require (
|
||||
golang.org/x/net v0.59.0 // indirect
|
||||
golang.org/x/sys v0.48.0 // indirect
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/klog/v2 v2.140.0 // indirect
|
||||
k8s.io/utils v0.0.0-20260626114624-be93311217bd // indirect
|
||||
|
||||
Generated
+11
-10
@@ -78,16 +78,17 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
@@ -113,8 +114,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -65,14 +65,15 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.7.2 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
@@ -88,7 +89,7 @@ require (
|
||||
golang.org/x/text v0.42.0 // indirect
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
|
||||
+20
-18
@@ -177,24 +177,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -235,8 +237,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
@@ -65,14 +65,15 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.7.2 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.7.2 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect
|
||||
go.opentelemetry.io/otel v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/log v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.47.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
@@ -90,7 +91,7 @@ require (
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
golang.org/x/tools v0.50.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
|
||||
google.golang.org/grpc v1.84.0 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
|
||||
+20
-18
@@ -179,24 +179,26 @@ go.etcd.io/raft/v3 v3.7.0/go.mod h1:6gX6T2X907DjnjsFLODnTxba77stjs84W9gTTI0GUNA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0 h1:Tq+E65HaNbZTeqcLw6QUhsV+/EIWdkfUH2CQzcrlE5M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.72.0/go.mod h1:A+EVhDakAj1waJBPhmTszZaSr08ww8MRRKy1nB1rqck=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
|
||||
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
|
||||
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
|
||||
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
|
||||
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
|
||||
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
|
||||
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
|
||||
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
|
||||
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
|
||||
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -242,8 +244,8 @@ gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
|
||||
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
|
||||
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
|
||||
Generated
Vendored
+3
-5
@@ -38,11 +38,9 @@ func SplitHostPort(hostport string) (host string, port int) {
|
||||
host = hostport[1:addrEnd]
|
||||
return host, port
|
||||
}
|
||||
} else {
|
||||
if i := strings.LastIndexByte(hostport, ':'); i < 0 {
|
||||
host = hostport
|
||||
return host, port
|
||||
}
|
||||
} else if !strings.Contains(hostport, ":") {
|
||||
host = hostport
|
||||
return host, port
|
||||
}
|
||||
|
||||
host, pStr, err := net.SplitHostPort(hostport)
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -4,4 +4,4 @@
|
||||
package otelrestful
|
||||
|
||||
// Version is the current release version of the go-restful instrumentation.
|
||||
const Version = "0.71.0"
|
||||
const Version = "0.72.0"
|
||||
Generated
Vendored
+1
-1
@@ -4,4 +4,4 @@
|
||||
package otelgrpc
|
||||
|
||||
// Version is the current release version of the gRPC instrumentation.
|
||||
const Version = "0.71.0"
|
||||
const Version = "0.72.0"
|
||||
+24
-5
@@ -10,12 +10,31 @@ import (
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Attribute keys that can be added to a span.
|
||||
// Legacy HTTP attribute keys retained for compatibility.
|
||||
const (
|
||||
ReadBytesKey = attribute.Key("http.read_bytes") // if anything was read from the request body, the total number of bytes read
|
||||
ReadErrorKey = attribute.Key("http.read_error") // If an error occurred while reading a request, the string of the error (io.EOF is not recorded)
|
||||
WroteBytesKey = attribute.Key("http.wrote_bytes") // if anything was written to the response writer, the total number of bytes written
|
||||
WriteErrorKey = attribute.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded)
|
||||
// ReadBytesKey is the attribute key for the number of bytes returned by an
|
||||
// individual read from an HTTP request body.
|
||||
//
|
||||
// Deprecated: there is no direct semantic-convention replacement.
|
||||
ReadBytesKey = attribute.Key("http.read_bytes")
|
||||
|
||||
// ReadErrorKey is the attribute key for the string form of a non-EOF error
|
||||
// returned while reading an HTTP request body.
|
||||
//
|
||||
// Deprecated: there is no direct semantic-convention replacement.
|
||||
ReadErrorKey = attribute.Key("http.read_error")
|
||||
|
||||
// WroteBytesKey is the attribute key for the number of bytes returned by an
|
||||
// individual write to an HTTP response body.
|
||||
//
|
||||
// Deprecated: there is no direct semantic-convention replacement.
|
||||
WroteBytesKey = attribute.Key("http.wrote_bytes")
|
||||
|
||||
// WriteErrorKey is the attribute key for the string form of a non-EOF error
|
||||
// returned while writing an HTTP response body.
|
||||
//
|
||||
// Deprecated: there is no direct semantic-convention replacement.
|
||||
WriteErrorKey = attribute.Key("http.write_error")
|
||||
)
|
||||
|
||||
// Filter is a predicate used to determine whether a given http.request should
|
||||
|
||||
+7
-6
@@ -143,14 +143,15 @@ const (
|
||||
)
|
||||
|
||||
// WithMessageEvents configures the Handler to record the specified events
|
||||
// (span.AddEvent) on spans. By default only summary attributes are added at the
|
||||
// end of the request.
|
||||
// (span.AddEvent) on spans. By default, no read or write events are recorded.
|
||||
//
|
||||
// Valid events are:
|
||||
// - ReadEvents: Record the number of bytes read after every http.Request.Body.Read
|
||||
// using the ReadBytesKey
|
||||
// - WriteEvents: Record the number of bytes written after every http.ResponeWriter.Write
|
||||
// using the WriteBytesKey
|
||||
// - ReadEvents: Record a "read" span event after every http.Request.Body.Read.
|
||||
// - WriteEvents: Record a "write" span event after every http.ResponseWriter.Write.
|
||||
//
|
||||
// The events do not include per-call byte-count attributes. Total request and
|
||||
// response body sizes are recorded on the span according to HTTP semantic
|
||||
// conventions.
|
||||
func WithMessageEvents(events ...Event) Option {
|
||||
return optionFunc(func(c *config) {
|
||||
for _, e := range events {
|
||||
|
||||
+20
-11
@@ -129,8 +129,8 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
|
||||
readRecordFunc := func(int64) {}
|
||||
if h.readEvent {
|
||||
readRecordFunc = func(n int64) {
|
||||
span.AddEvent("read", trace.WithAttributes(ReadBytesKey.Int64(n)))
|
||||
readRecordFunc = func(int64) {
|
||||
span.AddEvent("read")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
|
||||
writeRecordFunc := func(int64) {}
|
||||
if h.writeEvent {
|
||||
writeRecordFunc = func(n int64) {
|
||||
span.AddEvent("write", trace.WithAttributes(WroteBytesKey.Int64(n)))
|
||||
writeRecordFunc = func(int64) {
|
||||
span.AddEvent("write")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,12 +180,21 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
if !found {
|
||||
ctx = ContextWithLabeler(ctx, labeler)
|
||||
}
|
||||
rCtx := r.WithContext(ctx)
|
||||
defer func() {
|
||||
// Copy MultipartForm back to the original request so net/http can
|
||||
// find and remove any temp files ParseMultipartForm created on the
|
||||
// copy. Deferred so the copy-back also runs during panic unwinding,
|
||||
// letting net/http cleanup paths that still run (HTTP/2 handler
|
||||
// recovery, outer recovery middleware) find the form.
|
||||
if rCtx.MultipartForm != nil {
|
||||
r.MultipartForm = rCtx.MultipartForm
|
||||
}
|
||||
}()
|
||||
next.ServeHTTP(w, rCtx)
|
||||
|
||||
r = r.WithContext(ctx)
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
if r.Pattern != "" {
|
||||
span.SetName(h.spanNameFormatter(h.operation, r))
|
||||
if rCtx.Pattern != "" {
|
||||
span.SetName(h.spanNameFormatter(h.operation, rCtx))
|
||||
}
|
||||
|
||||
statusCode := rww.StatusCode()
|
||||
@@ -204,9 +213,9 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
ServerName: h.server,
|
||||
ResponseSize: bytesWritten,
|
||||
MetricAttributes: semconv.MetricAttributes{
|
||||
Req: r,
|
||||
Req: rCtx,
|
||||
StatusCode: statusCode,
|
||||
AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(r)...),
|
||||
AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(rCtx)...),
|
||||
},
|
||||
MetricData: semconv.MetricData{
|
||||
RequestSize: bytesRead,
|
||||
|
||||
Generated
Vendored
+3
-5
@@ -38,11 +38,9 @@ func SplitHostPort(hostport string) (host string, port int) {
|
||||
host = hostport[1:addrEnd]
|
||||
return host, port
|
||||
}
|
||||
} else {
|
||||
if i := strings.LastIndexByte(hostport, ':'); i < 0 {
|
||||
host = hostport
|
||||
return host, port
|
||||
}
|
||||
} else if !strings.Contains(hostport, ":") {
|
||||
host = hostport
|
||||
return host, port
|
||||
}
|
||||
|
||||
host, pStr, err := net.SplitHostPort(hostport)
|
||||
|
||||
+24
@@ -56,3 +56,27 @@ func LabelerFromContext(ctx context.Context) (*Labeler, bool) {
|
||||
}
|
||||
return l, ok
|
||||
}
|
||||
|
||||
// clientLabelerContextKey is a separate context key for the client-side Labeler.
|
||||
// This prevents server-side Labeler attributes (e.g., http.route) from leaking
|
||||
// into client-side metrics when a server handler propagates its request context
|
||||
// into an outbound HTTP client request.
|
||||
const clientLabelerContextKey labelerContextKeyType = 1
|
||||
|
||||
// ContextWithClientLabeler returns a new context with the provided Labeler instance
|
||||
// for use with client-side HTTP instrumentation (otelhttp.Transport).
|
||||
// Attributes added to this labeler will be attached to client-side metrics.
|
||||
func ContextWithClientLabeler(parent context.Context, l *Labeler) context.Context {
|
||||
return context.WithValue(parent, clientLabelerContextKey, l)
|
||||
}
|
||||
|
||||
// ClientLabelerFromContext retrieves a Labeler instance from the provided context
|
||||
// for use with client-side HTTP instrumentation. If no Labeler was found, a new,
|
||||
// empty Labeler is returned and the second return value is false.
|
||||
func ClientLabelerFromContext(ctx context.Context) (*Labeler, bool) {
|
||||
l, ok := ctx.Value(clientLabelerContextKey).(*Labeler)
|
||||
if !ok {
|
||||
l = &Labeler{}
|
||||
}
|
||||
return l, ok
|
||||
}
|
||||
Generated
Vendored
+180
-52
@@ -9,6 +9,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
@@ -19,7 +20,6 @@ import (
|
||||
otelsemconv "go.opentelemetry.io/otel/semconv/v1.43.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
|
||||
)
|
||||
|
||||
@@ -82,6 +82,142 @@ func defaultTransportFormatter(_ string, r *http.Request) string {
|
||||
return "HTTP " + r.Method
|
||||
}
|
||||
|
||||
// requestTracker tracks the request body lifecycle of a single RoundTrip and
|
||||
// records the client metrics exactly once, after the request body reaches a
|
||||
// final state.
|
||||
//
|
||||
// A single tracker is allocated per request with a body, replacing the
|
||||
// body-wrapper allocation of the untracked implementation: the first request
|
||||
// body is wrapped by the embedded first field, and the lifecycle state is
|
||||
// held in explicit fields with methods instead of escaping closures. Only
|
||||
// GetBody retries allocate an additional trackedRequestBody.
|
||||
type requestTracker struct {
|
||||
transport *Transport
|
||||
first trackedRequestBody
|
||||
|
||||
originalGetBody func() (io.ReadCloser, error)
|
||||
|
||||
// mu protects body, published, and recorded. Body close callbacks may
|
||||
// fire on a different goroutine (e.g. during transport retries or
|
||||
// asynchronous closes) while the main goroutine publishes the metric
|
||||
// data after RoundTrip returns.
|
||||
mu sync.Mutex
|
||||
body *trackedRequestBody // Last wrapped request body; nil records no data.
|
||||
published bool
|
||||
recorded bool
|
||||
|
||||
// Metric data published when RoundTrip returns; immutable afterwards.
|
||||
ctx context.Context
|
||||
duration time.Duration
|
||||
opts semconv.MetricOpts
|
||||
}
|
||||
|
||||
func newRequestTracker(t *Transport, r *http.Request) *requestTracker {
|
||||
rt := &requestTracker{transport: t}
|
||||
rt.first = trackedRequestBody{body: r.Body, tracker: rt}
|
||||
rt.body = &rt.first
|
||||
r.Body = &rt.first
|
||||
if r.GetBody != nil {
|
||||
rt.originalGetBody = r.GetBody
|
||||
r.GetBody = rt.getBody
|
||||
}
|
||||
return rt
|
||||
}
|
||||
|
||||
func (rt *requestTracker) getBody() (io.ReadCloser, error) {
|
||||
b, err := rt.originalGetBody()
|
||||
if err != nil {
|
||||
// The underlying transport will fail to make a retry request,
|
||||
// hence, record no data.
|
||||
rt.setBody(nil)
|
||||
return nil, err
|
||||
}
|
||||
if b == nil || b == http.NoBody {
|
||||
return b, nil
|
||||
}
|
||||
tb := &trackedRequestBody{body: b, tracker: rt}
|
||||
rt.setBody(tb)
|
||||
return tb, nil
|
||||
}
|
||||
|
||||
func (rt *requestTracker) setBody(b *trackedRequestBody) {
|
||||
rt.mu.Lock()
|
||||
rt.body = b
|
||||
rt.mu.Unlock()
|
||||
}
|
||||
|
||||
// publish stores the metric data gathered when RoundTrip returns and records
|
||||
// the metrics if the request body already reached a final state.
|
||||
func (rt *requestTracker) publish(ctx context.Context, d time.Duration, opts semconv.MetricOpts) {
|
||||
rt.mu.Lock()
|
||||
rt.ctx = ctx
|
||||
rt.duration = d
|
||||
rt.opts = opts
|
||||
rt.published = true
|
||||
rt.mu.Unlock()
|
||||
rt.maybeRecord()
|
||||
}
|
||||
|
||||
// maybeRecord records the client metrics once the metric data has been
|
||||
// published and the request body has reached a final state. Close is the
|
||||
// only authoritative completion signal for a non-nil body: a body may yield
|
||||
// more bytes than its declared ContentLength, so a read count is never proof
|
||||
// of completion.
|
||||
func (rt *requestTracker) maybeRecord() {
|
||||
rt.mu.Lock()
|
||||
body := rt.body
|
||||
record := rt.published && !rt.recorded && (body == nil || body.closed.Load())
|
||||
if record {
|
||||
rt.recorded = true
|
||||
}
|
||||
rt.mu.Unlock()
|
||||
if !record {
|
||||
return
|
||||
}
|
||||
|
||||
// The winning caller evaluates the request size here so the recorded
|
||||
// value reflects the latest byte count.
|
||||
var requestSize int64
|
||||
if body != nil {
|
||||
requestSize = body.read.Load()
|
||||
}
|
||||
rt.transport.semconv.RecordMetrics(
|
||||
rt.ctx,
|
||||
semconv.MetricData{
|
||||
RequestSize: requestSize,
|
||||
RequestDuration: rt.duration,
|
||||
},
|
||||
rt.opts,
|
||||
)
|
||||
}
|
||||
|
||||
// trackedRequestBody wraps a request body to count read bytes and signal the
|
||||
// tracker when the body is closed.
|
||||
type trackedRequestBody struct {
|
||||
body io.ReadCloser
|
||||
tracker *requestTracker
|
||||
|
||||
read atomic.Int64
|
||||
closed atomic.Bool
|
||||
}
|
||||
|
||||
var _ io.ReadCloser = (*trackedRequestBody)(nil)
|
||||
|
||||
func (b *trackedRequestBody) Read(p []byte) (int, error) {
|
||||
n, err := b.body.Read(p)
|
||||
b.read.Add(int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (b *trackedRequestBody) Close() error {
|
||||
// Finalize telemetry before delegating to the underlying Close, which
|
||||
// may block (mirroring wrappedBody.Close). Otherwise a blocking close
|
||||
// could suppress client metrics indefinitely.
|
||||
b.closed.Store(true)
|
||||
b.tracker.maybeRecord()
|
||||
return b.body.Close()
|
||||
}
|
||||
|
||||
// RoundTrip creates a Span and propagates its context via the provided request's headers
|
||||
// before handing the request to the configured base RoundTripper. The created span will
|
||||
// end when the response body is closed or when a read from the body returns io.EOF.
|
||||
@@ -110,33 +246,20 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
ctx = httptrace.WithClientTrace(ctx, t.clientTrace(ctx))
|
||||
}
|
||||
|
||||
labeler, found := LabelerFromContext(ctx)
|
||||
labeler, found := ClientLabelerFromContext(ctx)
|
||||
if !found {
|
||||
ctx = ContextWithLabeler(ctx, labeler)
|
||||
ctx = ContextWithClientLabeler(ctx, labeler)
|
||||
}
|
||||
|
||||
r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request.
|
||||
|
||||
var lastBW *request.BodyWrapper // Records the last body wrapper. Can be nil.
|
||||
maybeWrapBody := func(body io.ReadCloser) io.ReadCloser {
|
||||
if body == nil || body == http.NoBody {
|
||||
return body
|
||||
}
|
||||
bw := request.NewBodyWrapper(body, func(int64) {})
|
||||
lastBW = bw
|
||||
return bw
|
||||
}
|
||||
r.Body = maybeWrapBody(r.Body)
|
||||
if r.GetBody != nil {
|
||||
originalGetBody := r.GetBody
|
||||
r.GetBody = func() (io.ReadCloser, error) {
|
||||
b, err := originalGetBody()
|
||||
if err != nil {
|
||||
lastBW = nil // The underlying transport will fail to make a retry request, hence, record no data.
|
||||
return nil, err
|
||||
}
|
||||
return maybeWrapBody(b), nil
|
||||
}
|
||||
// Track the request body lifecycle so metrics report the final read
|
||||
// size even when the transport keeps reading the body after RoundTrip
|
||||
// returns. Bodyless requests allocate no tracker and record
|
||||
// synchronously below.
|
||||
var tracker *requestTracker
|
||||
if r.Body != nil && r.Body != http.NoBody {
|
||||
tracker = newRequestTracker(t, r)
|
||||
}
|
||||
|
||||
span.SetAttributes(t.semconv.RequestTraceAttrs(r)...)
|
||||
@@ -147,29 +270,32 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
res, err = ensureResponseBody(t.rt, r, res)
|
||||
}
|
||||
|
||||
// Record the metrics on error or no error.
|
||||
requestDuration := time.Since(requestStartTime)
|
||||
statusCode := 0
|
||||
if err == nil {
|
||||
statusCode = res.StatusCode
|
||||
}
|
||||
var requestSize int64
|
||||
if lastBW != nil {
|
||||
requestSize = lastBW.BytesRead()
|
||||
metricOpts := t.semconv.MetricOptions(semconv.MetricAttributes{
|
||||
Req: r,
|
||||
Resp: res,
|
||||
StatusCode: statusCode,
|
||||
Err: err,
|
||||
AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...),
|
||||
})
|
||||
|
||||
if tracker != nil {
|
||||
// Delay metric recording until the request body reaches a final
|
||||
// state. The transport can continue reading the body after
|
||||
// RoundTrip returns, including on errors, since RoundTrippers may
|
||||
// close the request body asynchronously.
|
||||
tracker.publish(ctx, requestDuration, metricOpts)
|
||||
} else {
|
||||
t.semconv.RecordMetrics(
|
||||
ctx,
|
||||
semconv.MetricData{RequestDuration: requestDuration},
|
||||
metricOpts,
|
||||
)
|
||||
}
|
||||
t.semconv.RecordMetrics(
|
||||
ctx,
|
||||
semconv.MetricData{
|
||||
RequestSize: requestSize,
|
||||
RequestDuration: time.Since(requestStartTime),
|
||||
},
|
||||
t.semconv.MetricOptions(semconv.MetricAttributes{
|
||||
Req: r,
|
||||
Resp: res,
|
||||
StatusCode: statusCode,
|
||||
Err: err,
|
||||
AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...),
|
||||
}),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
span.SetAttributes(otelsemconv.ErrorType(err))
|
||||
@@ -263,8 +389,7 @@ func (wb *wrappedBody) Read(b []byte) (int, error) {
|
||||
case nil:
|
||||
// nothing to do here but fall through to the return
|
||||
case io.EOF:
|
||||
wb.recordBytesRead()
|
||||
wb.span.End()
|
||||
wb.recordMetricsOnce()
|
||||
default:
|
||||
wb.span.SetAttributes(otelsemconv.ErrorType(err))
|
||||
wb.span.SetStatus(codes.Error, err.Error())
|
||||
@@ -272,21 +397,24 @@ func (wb *wrappedBody) Read(b []byte) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// recordBytesRead is a function that ensures the number of bytes read is recorded once and only once.
|
||||
func (wb *wrappedBody) recordBytesRead() {
|
||||
// note: it is more performant (and equally correct) to use atomic.Bool over sync.Once here. In the event that
|
||||
// two goroutines are racing to call this method, the number of bytes read will no longer increase. Using
|
||||
// CompareAndSwap allows later goroutines to return quickly and not block waiting for the race winner to finish
|
||||
// calling wb.record(wb.read.Load()).
|
||||
// recordMetricsOnce ensures the final number of bytes read is recorded once.
|
||||
func (wb *wrappedBody) recordMetricsOnce() {
|
||||
// note: it is more performant (and equally correct) to use atomic.Bool
|
||||
// over sync.Once here. In the event that two goroutines are racing to
|
||||
// call this method, the number of bytes read will no longer increase.
|
||||
// Using CompareAndSwap allows later goroutines to return quickly and not
|
||||
// block waiting for the race winner to finish calling
|
||||
// wb.record(wb.read.Load()).
|
||||
if wb.recorded.CompareAndSwap(false, true) {
|
||||
// Record the total number of bytes read
|
||||
wb.record(wb.read.Load())
|
||||
wb.span.End()
|
||||
}
|
||||
}
|
||||
|
||||
func (wb *wrappedBody) Close() error {
|
||||
wb.recordBytesRead()
|
||||
wb.span.End()
|
||||
// Finalize telemetry before delegating to the underlying Close, which
|
||||
// may block (e.g. upgraded streams or custom RoundTripper bodies).
|
||||
wb.recordMetricsOnce()
|
||||
if wb.body != nil {
|
||||
return wb.body.Close()
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,4 +4,4 @@
|
||||
package otelhttp
|
||||
|
||||
// Version is the current release version of the otelhttp instrumentation.
|
||||
const Version = "0.71.0"
|
||||
const Version = "0.72.0"
|
||||
+4
-8
@@ -230,13 +230,6 @@ linters:
|
||||
- revive
|
||||
path: schema/v.*/types/.*
|
||||
text: avoid meaningless package names
|
||||
# TODO: Having appropriate comments for exported objects helps development,
|
||||
# even for objects in internal packages. Appropriate comments for all
|
||||
# exported objects should be added and this exclusion removed.
|
||||
- linters:
|
||||
- revive
|
||||
path: .*internal/.*
|
||||
text: exported (method|function|type|const) (.+) should have comment or be unexported
|
||||
# Yes, they are, but it's okay in a test.
|
||||
- linters:
|
||||
- revive
|
||||
@@ -272,7 +265,10 @@ formatters:
|
||||
- golines
|
||||
settings:
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
extra:
|
||||
group-params: true
|
||||
clothe-returns: true
|
||||
balance-calls: true
|
||||
goimports:
|
||||
local-prefixes:
|
||||
- go.opentelemetry.io/otel
|
||||
|
||||
+90
-1
@@ -11,6 +11,93 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
<!-- Released section -->
|
||||
<!-- Don't change this section unless doing release -->
|
||||
|
||||
## [1.47.0/0.69.0/0.23.0/0.1.0] - 2026-10-02
|
||||
|
||||
This release contains the first stable release of the OpenTelemetry Go Logs API and SDK.
|
||||
Our project stability guarantees now apply to the following modules:
|
||||
|
||||
- `go.opentelemetry.io/otel/log`
|
||||
- `go.opentelemetry.io/otel/sdk/log`
|
||||
|
||||
See our [versioning policy](VERSIONING.md) for more information about these stability guarantees.
|
||||
|
||||
### Added
|
||||
|
||||
- Add `String` method for `KeyValue` type in `go.opentelemetry.io/otel/attribute`. (#8205)
|
||||
- Add `String` method for `Set` type in `go.opentelemetry.io/otel/attribute`. (#8347)
|
||||
- Add `WithMaxExportBatchSize` to `go.opentelemetry.io/otel/sdk/metric` to configure the maximum export batch size for `PeriodicReader`. (#8960)
|
||||
- Add `WithAttributeValueDepthLimit`, `DefaultAttributeValueDepthLimit`, and `SpanLimits.AttributeValueDepthLimit` in `go.opentelemetry.io/otel/sdk/trace` to configure the maximum depth of span, event, link, and instrumentation scope attribute values. (#8938)
|
||||
- Add `WithAttributeValueDepthLimit` in `go.opentelemetry.io/otel/sdk/log` to configure the maximum depth of log record and instrumentation scope attribute values. (#8938)
|
||||
- Add `WithMaxResponseSize` to `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`,
|
||||
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`, and
|
||||
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8941)
|
||||
- Add experimental `ProbabilitySampler` in `go.opentelemetry.io/otel/sdk/trace/x` that conforms to the [OpenTelemetry specification's threshold-based sampling algorithm](https://opentelemetry.io/docs/specs/otel/trace/sdk/#probabilitysampler). (#8123)
|
||||
- Add experimental `*Binder` extension interfaces in `go.opentelemetry.io/otel/metric/x` for instruments that support binding attributes ahead of time. (#8760)
|
||||
- Add the experimental `Finisher` synchronous metric instrument extension interface to `go.opentelemetry.io/otel/metric/x`. (#8906)
|
||||
|
||||
### Changed
|
||||
|
||||
- Use the [OpenTelemetry Attribute Collection representation for non-OTLP protocols](https://opentelemetry.io/docs/specs/otel/common/#attribute-collection-representation-for-non-otlp) for metric data diffs in `go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest`. (#8993)
|
||||
- Apply a maximum depth of 64 by default to span, event, link, log record, and instrumentation scope attribute values in `go.opentelemetry.io/otel/sdk/trace` and `go.opentelemetry.io/otel/sdk/log`. (#8938)
|
||||
- Reduce allocations when applying attribute value length limits in `go.opentelemetry.io/otel/sdk/trace` and `go.opentelemetry.io/otel/sdk/log` by rebuilding composite values only when truncation is needed. (#8912)
|
||||
- Decode `traceparent` using a hex lookup table in `go.opentelemetry.io/otel/propagation`, which rejects the specification-disallowed upper-case characters without a separate scan of the header. (#8739)
|
||||
- Decode all characters at constant indices in `TraceIDFromHex` and `SpanIDFromHex` in `go.opentelemetry.io/otel/trace` to eliminate bounds checks. (#8740)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Count valid U+FFFD replacement characters toward attribute value length limits in `go.opentelemetry.io/otel/trace`, `go.opentelemetry.io/otel/sdk/trace`, and `go.opentelemetry.io/otel/sdk/log`.
|
||||
- Truncate string attribute values to empty strings when the configured length limit is zero, including malformed UTF-8, in `go.opentelemetry.io/otel/trace`, `go.opentelemetry.io/otel/sdk/trace`, and `go.opentelemetry.io/otel/sdk/log`. (#9054)
|
||||
- Fix a data race in `NewPeriodicReader` where `r.inst` was assigned after the background goroutine was launched in `go.opentelemetry.io/otel/sdk/metric`. (#9028)
|
||||
- Prevent precision loss for large `int64` values in `Sum`, `Histogram`, and `ExponentialHistogram` aggregations in `go.opentelemetry.io/otel/sdk/metric`. (#8981)
|
||||
- Ensure `grpc.DialOption` values passed via `WithDialOption` take precedence over conflicting internally-computed defaults in
|
||||
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`,
|
||||
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`, and
|
||||
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#8805, #8834, #8836)
|
||||
- Treat overflowing `OTEL_METRIC_EXPORT_INTERVAL` and `OTEL_METRIC_EXPORT_TIMEOUT` values as invalid in `go.opentelemetry.io/otel/sdk/metric`. (#8800)
|
||||
- Prevent a panic in `NewFixedSizeReservoir` and `FixedSizeReservoirProvider` when given a negative size in `go.opentelemetry.io/otel/sdk/metric/exemplar`; negative sizes are now clamped to zero, consistent with a size of zero. (#8832)
|
||||
- Preserve exponential histogram `ZeroThreshold` during OTLP metric export in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#8801)
|
||||
- Ensure metric helpers in `go.opentelemetry.io/otel/semconv/v1.32.0`, `go.opentelemetry.io/otel/semconv/v1.33.0`, and `go.opentelemetry.io/otel/semconv/v1.34.0` record measurements only once when no attributes are provided. (#8849)
|
||||
- Treat empty `OTEL_TRACES_SAMPLER` and `OTEL_TRACES_SAMPLER_ARG` values as unset in `go.opentelemetry.io/otel/sdk/trace`. (#8873)
|
||||
- Normalize global `OTEL_EXPORTER_OTLP_ENDPOINT` path joining in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` so trailing-slash base URLs do not produce double-slash log export paths. (#8864)
|
||||
- Prevent a deadlock when formatting an error passed to `RecordError` calls back into the span in `go.opentelemetry.io/otel/sdk/trace`. (#8815)
|
||||
- Prevent `SimpleSpanProcessor.Shutdown` from panicking when constructed with a nil exporter in `go.opentelemetry.io/otel/sdk/trace`. (#8844)
|
||||
- Propagate invalid exponential histogram scale errors to Prometheus exporter self-observability metrics in `go.opentelemetry.io/otel/exporters/prometheus`. (#8839)
|
||||
- Retain instrument advisory attributes configured with `go.opentelemetry.io/otel/metric/x.WithDefaultAttributes` when a matching View in `go.opentelemetry.io/otel/sdk/metric` does not specify an attribute filter. (#8859)
|
||||
- Ignore HTTP URL paths when building OTLP/gRPC metric exporter targets from `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`, while preserving `unix://` and `unix-abstract://` targets; treat `unix-abstract://` endpoints as insecure in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#8862)
|
||||
- Ignore HTTP(S) paths when deriving gRPC trace exporter endpoints from `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#8852)
|
||||
- Bound memory used while parsing dense W3C property metadata by storing it compactly and materializing `Property` values on demand in `go.opentelemetry.io/otel/baggage` and `go.opentelemetry.io/otel/propagation`.
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove the experimental `OTEL_GO_X_METRIC_EXPORT_BATCH_SIZE` environment variable in `go.opentelemetry.io/otel/sdk/metric`.
|
||||
Use the `WithMaxExportBatchSize` option instead. (#8960)
|
||||
|
||||
## [1.47.0-rc.1] - 2026-08-28
|
||||
|
||||
This is a release candidate for the v1.47.0 release.
|
||||
That release is expected to include the `v1` release of the OpenTelemetry Go Logs API and SDK and will provide stability guarantees for the following modules:
|
||||
|
||||
- `go.opentelemetry.io/otel/log`
|
||||
- `go.opentelemetry.io/otel/sdk/log`
|
||||
|
||||
See our [versioning policy](VERSIONING.md) for more information about these stability guarantees.
|
||||
|
||||
### Added
|
||||
|
||||
- Add `Logger`, `GetLoggerProvider`, and `SetLoggerProvider` to `go.opentelemetry.io/otel`. (#8874)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecate `go.opentelemetry.io/otel/log/global`; use the equivalent APIs in `go.opentelemetry.io/otel`. (#8874)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Ignore attempts to unregister unknown span processors in `go.opentelemetry.io/otel/sdk/trace`. (#8840)
|
||||
|
||||
### Removed
|
||||
|
||||
- Drop support for [Go 1.25]. (#8876)
|
||||
|
||||
## [1.46.0/0.68.0/0.22.0/0.0.19] - 2026-08-25
|
||||
|
||||
This release is the last to support [Go 1.25].
|
||||
@@ -3810,7 +3897,9 @@ It contains api and sdk for trace and meter.
|
||||
- CircleCI build CI manifest files.
|
||||
- CODEOWNERS file to track owners of this project.
|
||||
|
||||
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.46.0...HEAD
|
||||
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.47.0...HEAD
|
||||
[1.47.0/0.69.0/0.23.0/0.1.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.47.0
|
||||
[1.47.0-rc.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.47.0-rc.1
|
||||
[1.46.0/0.68.0/0.22.0/0.0.19]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.46.0
|
||||
[1.45.0/0.67.0/0.21.0/0.0.18]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.45.0
|
||||
[1.44.0/0.66.0/0.20.0/0.0.17]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.44.0
|
||||
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
# Instructions for Claude Code
|
||||
|
||||
@AGENTS.md
|
||||
+1
-1
@@ -12,6 +12,6 @@
|
||||
# https://help.github.com/en/articles/about-code-owners
|
||||
#
|
||||
|
||||
* @MrAlias @XSAM @dashpole @pellared @dmathieu @flc1125
|
||||
* @MrAlias @XSAM @dashpole @pellared @dmathieu @flc1125 @ps-mir
|
||||
|
||||
CODEOWNERS @MrAlias @pellared @dashpole @XSAM @dmathieu
|
||||
+11
-9
@@ -779,7 +779,7 @@ func newInstrumentation() (*instrumentation, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
meter := otel.GetMeterProvider().Meter(
|
||||
"<component-package-name>",
|
||||
metric.WithInstrumentationVersion(sdk.Version()),
|
||||
@@ -949,7 +949,7 @@ func BenchmarkExportSpans(b *testing.B) {
|
||||
{"ObsDisabled", false},
|
||||
{"ObsEnabled", true},
|
||||
}
|
||||
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
b.Run(scenario.name, func(b *testing.B) {
|
||||
b.Setenv(
|
||||
@@ -980,7 +980,7 @@ func newInstrumentation() (*instrumentation, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
m := otel.GetMeterProvider().Meter(/* initialize meter */)
|
||||
counter, err := otelconv.NewSDKComponentCounter(m)
|
||||
// Use the partially initialized counter if available.
|
||||
@@ -996,7 +996,7 @@ func newInstrumentation() *instrumentation {
|
||||
if !x.Observability.Enabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
m := otel.GetMeterProvider().Meter(/* initialize meter */)
|
||||
counter, err := otelconv.NewSDKComponentCounter(m)
|
||||
if err != nil {
|
||||
@@ -1023,7 +1023,7 @@ func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan)
|
||||
if e.inst.Enabled(ctx) {
|
||||
e.inst.recordSpanExportStarted(ctx, len(spans))
|
||||
}
|
||||
|
||||
|
||||
err := e.doExport(ctx, spans)
|
||||
|
||||
if e.inst.Enabled(ctx) {
|
||||
@@ -1043,11 +1043,11 @@ func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan)
|
||||
func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error {
|
||||
// ❌ Do not break the context propagation.
|
||||
e.inst.recordSpanExportStarted(context.Background(), len(spans))
|
||||
|
||||
|
||||
err := e.doExport(ctx, spans)
|
||||
|
||||
/* ... */
|
||||
|
||||
|
||||
return err
|
||||
}
|
||||
```
|
||||
@@ -1118,7 +1118,7 @@ func TestObservability(t *testing.T) {
|
||||
|
||||
// Reset component ID counter to ensure deterministic component names.
|
||||
componentIDCounter.Store(0)
|
||||
|
||||
|
||||
/* ... test code ... */
|
||||
}
|
||||
```
|
||||
@@ -1203,18 +1203,20 @@ For more information about the maintainer role, see the [community repository](h
|
||||
### Approvers
|
||||
|
||||
- [Flc](https://github.com/flc1125), Independent
|
||||
- [Puneet Singh](https://github.com/ps-mir), Independent
|
||||
|
||||
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
|
||||
|
||||
### Triagers
|
||||
|
||||
- [Alex Kats](https://github.com/akats7), Capital One
|
||||
- [Marc Schäfer](https://github.com/marcschaeferger), T&A SYSTEME GmbH
|
||||
|
||||
For more information about the triager role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).
|
||||
|
||||
### Emeritus
|
||||
|
||||
- [Aaron Clawson](https://github.com/MadVikingGod)
|
||||
- [Alex Kats](https://github.com/akats7)
|
||||
- [Anthony Mirabella](https://github.com/Aneurysm9)
|
||||
- [Cheng-Zhen Yang](https://github.com/scorpionknifes)
|
||||
- [Chester Cheung](https://github.com/hanyuancheung)
|
||||
|
||||
+2
-19
@@ -3,12 +3,11 @@
|
||||
[](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml)
|
||||
[](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main)
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel)
|
||||
[](https://goreportcard.com/report/go.opentelemetry.io/otel)
|
||||
[](https://scorecard.dev/viewer/?uri=github.com/open-telemetry/opentelemetry-go)
|
||||
[](https://www.bestpractices.dev/projects/9996)
|
||||
[](https://issues.oss-fuzz.com/issues?q=project:opentelemetry-go)
|
||||
[](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-go?ref=badge_shield&issueType=license)
|
||||
[](https://cloud-native.slack.com/archives/C01NPAXACKT)
|
||||
[](https://slack.cncf.io/)
|
||||
|
||||
OpenTelemetry-Go is the [Go](https://golang.org/) implementation of [OpenTelemetry](https://opentelemetry.io/).
|
||||
It provides a set of APIs to directly measure performance and behavior of your software and send this data to observability platforms.
|
||||
@@ -19,7 +18,7 @@ It provides a set of APIs to directly measure performance and behavior of your s
|
||||
|---------|--------------------|
|
||||
| Traces | Stable |
|
||||
| Metrics | Stable |
|
||||
| Logs | Beta[^1] |
|
||||
| Logs | Stable |
|
||||
|
||||
Progress and status specific to this repository is tracked in our
|
||||
[project boards](https://github.com/open-telemetry/opentelemetry-go/projects)
|
||||
@@ -29,8 +28,6 @@ and
|
||||
Project versioning information and stability guarantees can be found in the
|
||||
[versioning documentation](VERSIONING.md).
|
||||
|
||||
[^1]: https://github.com/orgs/open-telemetry/projects/43
|
||||
|
||||
### Compatibility
|
||||
|
||||
OpenTelemetry-Go ensures compatibility with the current supported versions of
|
||||
@@ -55,25 +52,18 @@ Currently, this project supports the following environments.
|
||||
|----------|------------|--------------|
|
||||
| Ubuntu | 1.27 | amd64 |
|
||||
| Ubuntu | 1.26 | amd64 |
|
||||
| Ubuntu | 1.25 | amd64 |
|
||||
| Ubuntu | 1.27 | 386 |
|
||||
| Ubuntu | 1.26 | 386 |
|
||||
| Ubuntu | 1.25 | 386 |
|
||||
| Ubuntu | 1.27 | arm64 |
|
||||
| Ubuntu | 1.26 | arm64 |
|
||||
| Ubuntu | 1.25 | arm64 |
|
||||
| macOS | 1.27 | amd64 |
|
||||
| macOS | 1.26 | amd64 |
|
||||
| macOS | 1.25 | amd64 |
|
||||
| macOS | 1.27 | arm64 |
|
||||
| macOS | 1.26 | arm64 |
|
||||
| macOS | 1.25 | arm64 |
|
||||
| Windows | 1.27 | amd64 |
|
||||
| Windows | 1.26 | amd64 |
|
||||
| Windows | 1.25 | amd64 |
|
||||
| Windows | 1.27 | 386 |
|
||||
| Windows | 1.26 | 386 |
|
||||
| Windows | 1.25 | 386 |
|
||||
|
||||
While this project should work for other systems, no compatibility guarantees
|
||||
are made for those systems currently.
|
||||
@@ -120,10 +110,3 @@ All officially supported exporters for the OpenTelemetry project are contained i
|
||||
## Contributing
|
||||
|
||||
See the [contributing documentation](CONTRIBUTING.md).
|
||||
|
||||
### Emeritus
|
||||
|
||||
- [Alex Kats](https://github.com/akats7), Triager
|
||||
|
||||
For more information about the emeritus role, see the
|
||||
[community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
|
||||
+3
@@ -21,6 +21,7 @@ func New() Hash {
|
||||
return Hash{d: xxhash.New()}
|
||||
}
|
||||
|
||||
// Uint64 hashes val into h, returning the updated Hash.
|
||||
func (h Hash) Uint64(val uint64) Hash {
|
||||
var buf [8]byte
|
||||
binary.LittleEndian.PutUint64(buf[:], val)
|
||||
@@ -40,10 +41,12 @@ func (h Hash) Bool(val bool) Hash { // nolint:revive // This is a hashing functi
|
||||
return h.Uint64(0)
|
||||
}
|
||||
|
||||
// Float64 hashes val into h, returning the updated Hash.
|
||||
func (h Hash) Float64(val float64) Hash {
|
||||
return h.Uint64(math.Float64bits(val))
|
||||
}
|
||||
|
||||
// Int64 hashes val into h, returning the updated Hash.
|
||||
func (h Hash) Int64(val int64) Hash {
|
||||
return h.Uint64(uint64(val)) // nolint:gosec // Overflow doesn't matter since we are hashing.
|
||||
}
|
||||
|
||||
+10
@@ -13,6 +13,16 @@ type KeyValue struct {
|
||||
Value Value
|
||||
}
|
||||
|
||||
// String returns a string representation of KeyValue using the
|
||||
// [OpenTelemetry Attribute representation for non-OTLP protocols] rules.
|
||||
//
|
||||
// The KeyValue is encoded as a JSON object containing a single key-value pair.
|
||||
//
|
||||
// [OpenTelemetry Attribute representation for non-OTLP protocols]: https://opentelemetry.io/docs/specs/otel/common/#attribute-representation-for-non-otlp
|
||||
func (kv KeyValue) String() string {
|
||||
return formatMap([]KeyValue{kv})
|
||||
}
|
||||
|
||||
// Valid reports whether kv is a valid OpenTelemetry attribute.
|
||||
func (kv KeyValue) Valid() bool {
|
||||
return kv.Key.Defined()
|
||||
|
||||
+15
@@ -409,6 +409,21 @@ func computeDataReflect(kvs []KeyValue) any {
|
||||
return at.Interface()
|
||||
}
|
||||
|
||||
// String returns a string representation of the Set using the
|
||||
// [OpenTelemetry Attribute Collection representation for non-OTLP protocols]
|
||||
// rules.
|
||||
//
|
||||
// The Set is encoded as a JSON object. A nil or empty Set is encoded as an
|
||||
// empty JSON object.
|
||||
//
|
||||
// [OpenTelemetry Attribute Collection representation for non-OTLP protocols]: https://opentelemetry.io/docs/specs/otel/common/#attribute-collection-representation-for-non-otlp
|
||||
func (l *Set) String() string {
|
||||
if l == nil || l.hash == 0 {
|
||||
return "{}"
|
||||
}
|
||||
return formatMapValue(l.data)
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of the Set.
|
||||
func (l *Set) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(l.data)
|
||||
|
||||
+167
-68
@@ -247,10 +247,78 @@ func (p properties) String() string {
|
||||
return strings.Join(props, propertyDelimiter)
|
||||
}
|
||||
|
||||
// validateMetadata validates non-empty W3C property elements without decoding
|
||||
// or materializing Property values. Empty elements are accepted to preserve
|
||||
// existing parsing behavior.
|
||||
func validateMetadata(raw string) (string, bool) {
|
||||
start := 0
|
||||
for end := 0; end <= len(raw); end++ {
|
||||
if end != len(raw) && raw[end] != propertyDelimiter[0] {
|
||||
continue
|
||||
}
|
||||
|
||||
if start != end {
|
||||
if _, ok := parsePropertyFields(raw[start:end]); !ok {
|
||||
return raw[start:end], false
|
||||
}
|
||||
}
|
||||
start = end + 1
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
||||
// normalizeMetadata removes empty property elements while preserving the raw
|
||||
// representation of all non-empty elements.
|
||||
func normalizeMetadata(metadata string) string {
|
||||
if metadata == "" ||
|
||||
(metadata[0] != propertyDelimiter[0] &&
|
||||
metadata[len(metadata)-1] != propertyDelimiter[0] &&
|
||||
!strings.Contains(metadata, propertyDelimiter+propertyDelimiter)) {
|
||||
return metadata
|
||||
}
|
||||
|
||||
var normalized strings.Builder
|
||||
normalized.Grow(len(metadata))
|
||||
for property := range strings.SplitSeq(metadata, propertyDelimiter) {
|
||||
if property == "" {
|
||||
continue
|
||||
}
|
||||
if normalized.Len() > 0 {
|
||||
_, _ = normalized.WriteString(propertyDelimiter)
|
||||
}
|
||||
_, _ = normalized.WriteString(property)
|
||||
}
|
||||
return normalized.String()
|
||||
}
|
||||
|
||||
func propertiesFromMetadata(metadata string) properties {
|
||||
if metadata == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
props := make(properties, 0, strings.Count(metadata, propertyDelimiter)+1)
|
||||
for pStr := range strings.SplitSeq(metadata, propertyDelimiter) {
|
||||
if pStr == "" {
|
||||
continue
|
||||
}
|
||||
p, err := parseProperty(pStr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
props = append(props, p)
|
||||
}
|
||||
return props
|
||||
}
|
||||
|
||||
// Member is a list-member of a baggage-string as defined by the W3C Baggage
|
||||
// specification.
|
||||
type Member struct {
|
||||
key, value string
|
||||
|
||||
// metadata contains the opaque W3C property suffix extracted from the wire
|
||||
// without the leading semicolon. properties contains API-created
|
||||
// properties. The fields are mutually exclusive.
|
||||
metadata string
|
||||
properties properties
|
||||
|
||||
// hasData indicates whether the created property contains data or not.
|
||||
@@ -307,21 +375,16 @@ func newInvalidMember() Member {
|
||||
return Member{}
|
||||
}
|
||||
|
||||
// parseMember attempts to decode a Member from the passed string. It returns
|
||||
// an error if the input is invalid according to the W3C Baggage
|
||||
// specification.
|
||||
// parseMember attempts to decode a Member from the passed string. Property
|
||||
// metadata grammar is validated without decoding or materializing properties.
|
||||
func parseMember(member string) (Member, error) {
|
||||
var props properties
|
||||
keyValue, properties, found := strings.Cut(member, propertyDelimiter)
|
||||
var metadata string
|
||||
keyValue, rawMetadata, found := strings.Cut(member, propertyDelimiter)
|
||||
if found {
|
||||
// Parse the member properties.
|
||||
for pStr := range strings.SplitSeq(properties, propertyDelimiter) {
|
||||
p, err := parseProperty(pStr)
|
||||
if err != nil {
|
||||
return newInvalidMember(), err
|
||||
}
|
||||
props = append(props, p)
|
||||
if invalid, ok := validateMetadata(rawMetadata); !ok {
|
||||
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidProperty, invalid)
|
||||
}
|
||||
metadata = normalizeMetadata(rawMetadata)
|
||||
}
|
||||
// Parse the member key/value pair.
|
||||
|
||||
@@ -349,7 +412,7 @@ func parseMember(member string) (Member, error) {
|
||||
}
|
||||
|
||||
value := replaceInvalidUTF8Sequences(len(rawVal), unescapeVal)
|
||||
return Member{key: key, value: value, properties: props, hasData: true}, nil
|
||||
return Member{key: key, value: value, metadata: metadata, hasData: true}, nil
|
||||
}
|
||||
|
||||
// replaceInvalidUTF8Sequences replaces invalid UTF-8 sequences with '�'.
|
||||
@@ -399,10 +462,14 @@ func (m Member) Key() string { return m.key }
|
||||
func (m Member) Value() string { return m.value }
|
||||
|
||||
// Properties returns a copy of the Member properties.
|
||||
func (m Member) Properties() []Property { return m.properties.Copy() }
|
||||
func (m Member) Properties() []Property {
|
||||
if m.metadata != "" {
|
||||
return propertiesFromMetadata(m.metadata)
|
||||
}
|
||||
return m.properties.Copy()
|
||||
}
|
||||
|
||||
// String encodes Member into a header string compliant with the W3C Baggage
|
||||
// specification.
|
||||
// String encodes Member into a baggage header string.
|
||||
// It would return empty string if the key is invalid with the W3C Baggage
|
||||
// specification. This could happen for a UTF-8 key, as it may contain
|
||||
// invalid characters.
|
||||
@@ -413,12 +480,31 @@ func (m Member) String() string {
|
||||
}
|
||||
|
||||
s := m.key + keyValueDelimiter + valueEscape(m.value)
|
||||
if len(m.properties) > 0 {
|
||||
if m.metadata != "" {
|
||||
s += propertyDelimiter + m.metadata
|
||||
} else if len(m.properties) > 0 {
|
||||
s += propertyDelimiter + m.properties.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func memberFromItem(key string, item baggage.Item) Member {
|
||||
return Member{
|
||||
key: key,
|
||||
value: item.Value(),
|
||||
metadata: item.Metadata(),
|
||||
properties: fromInternalProperties(item.Properties()),
|
||||
hasData: true,
|
||||
}
|
||||
}
|
||||
|
||||
func itemFromMember(member Member) baggage.Item {
|
||||
if member.metadata != "" {
|
||||
return baggage.NewItemWithMetadata(member.value, member.metadata)
|
||||
}
|
||||
return baggage.NewItemWithProperties(member.value, member.properties.asInternal())
|
||||
}
|
||||
|
||||
// Baggage is a list of baggage members representing the baggage-string as
|
||||
// defined by the W3C Baggage specification.
|
||||
type Baggage struct { //nolint:golint
|
||||
@@ -444,10 +530,7 @@ func New(members ...Member) (Baggage, error) {
|
||||
return Baggage{}, errInvalidMember
|
||||
}
|
||||
// OpenTelemetry resolves duplicates by last-one-wins.
|
||||
b[m.key] = baggage.Item{
|
||||
Value: m.value,
|
||||
Properties: m.properties.asInternal(),
|
||||
}
|
||||
b[m.key] = itemFromMember(m)
|
||||
}
|
||||
|
||||
var truncateErr error
|
||||
@@ -467,11 +550,7 @@ func New(members ...Member) (Baggage, error) {
|
||||
totalBytes := 0
|
||||
first := true
|
||||
for k := range b {
|
||||
m := Member{
|
||||
key: k,
|
||||
value: b[k].Value,
|
||||
properties: fromInternalProperties(b[k].Properties),
|
||||
}
|
||||
m := memberFromItem(k, b[k])
|
||||
memberSize := len(m.String())
|
||||
if !first {
|
||||
memberSize++ // comma separator
|
||||
@@ -563,10 +642,7 @@ func Parse(bStr string) (Baggage, error) {
|
||||
}
|
||||
|
||||
// OpenTelemetry resolves duplicates by last-one-wins.
|
||||
b[m.key] = baggage.Item{
|
||||
Value: m.value,
|
||||
Properties: m.properties.asInternal(),
|
||||
}
|
||||
b[m.key] = itemFromMember(m)
|
||||
sizes[m.key] = memberBytes
|
||||
totalBytes = newTotalBytes
|
||||
}
|
||||
@@ -597,12 +673,7 @@ func (b Baggage) Member(key string) Member {
|
||||
return newInvalidMember()
|
||||
}
|
||||
|
||||
return Member{
|
||||
key: key,
|
||||
value: v.Value,
|
||||
properties: fromInternalProperties(v.Properties),
|
||||
hasData: true,
|
||||
}
|
||||
return memberFromItem(key, v)
|
||||
}
|
||||
|
||||
// Members returns all the baggage list-members.
|
||||
@@ -617,12 +688,7 @@ func (b Baggage) Members() []Member {
|
||||
|
||||
members := make([]Member, 0, len(b.list))
|
||||
for k, v := range b.list {
|
||||
members = append(members, Member{
|
||||
key: k,
|
||||
value: v.Value,
|
||||
properties: fromInternalProperties(v.Properties),
|
||||
hasData: true,
|
||||
})
|
||||
members = append(members, memberFromItem(k, v))
|
||||
}
|
||||
return members
|
||||
}
|
||||
@@ -652,10 +718,7 @@ func (b Baggage) SetMember(member Member) (Baggage, error) {
|
||||
list[k] = v
|
||||
}
|
||||
|
||||
list[member.key] = baggage.Item{
|
||||
Value: member.value,
|
||||
Properties: member.properties.asInternal(),
|
||||
}
|
||||
list[member.key] = itemFromMember(member)
|
||||
|
||||
return Baggage{list: list}, nil
|
||||
}
|
||||
@@ -692,11 +755,7 @@ func (b Baggage) Len() int {
|
||||
func (b Baggage) String() string {
|
||||
members := make([]string, 0, len(b.list))
|
||||
for k, v := range b.list {
|
||||
s := Member{
|
||||
key: k,
|
||||
value: v.Value,
|
||||
properties: fromInternalProperties(v.Properties),
|
||||
}.String()
|
||||
s := memberFromItem(k, v).String()
|
||||
|
||||
// Ignored empty members.
|
||||
if s != "" {
|
||||
@@ -706,9 +765,14 @@ func (b Baggage) String() string {
|
||||
return strings.Join(members, listDelimiter)
|
||||
}
|
||||
|
||||
// parsePropertyInternal attempts to decode a Property from the passed string.
|
||||
// It follows the spec at https://www.w3.org/TR/baggage/#definition.
|
||||
func parsePropertyInternal(s string) (p Property, ok bool) {
|
||||
type propertyFields struct {
|
||||
key, rawValue string
|
||||
hasValue bool
|
||||
}
|
||||
|
||||
// parsePropertyFields validates and locates a property's fields without
|
||||
// decoding or allocating them.
|
||||
func parsePropertyFields(s string) (fields propertyFields, ok bool) {
|
||||
// For the entire function we will use " key = value " as an example.
|
||||
// Attempting to parse the key.
|
||||
// First skip spaces at the beginning "< >key = value " (they could be empty).
|
||||
@@ -727,7 +791,7 @@ func parsePropertyInternal(s string) (p Property, ok bool) {
|
||||
// If we couldn't find any valid key character,
|
||||
// it means the key is either empty or invalid.
|
||||
if keyStart == keyEnd {
|
||||
return p, ok
|
||||
return fields, ok
|
||||
}
|
||||
|
||||
// Skip spaces after the key: " key< >= value ".
|
||||
@@ -735,15 +799,14 @@ func parsePropertyInternal(s string) (p Property, ok bool) {
|
||||
|
||||
if index == len(s) {
|
||||
// A key can have no value, like: " key ".
|
||||
ok = true
|
||||
p.key = s[keyStart:keyEnd]
|
||||
return p, ok
|
||||
fields.key = s[keyStart:keyEnd]
|
||||
return fields, true
|
||||
}
|
||||
|
||||
// If we have not reached the end and we can't find the '=' delimiter,
|
||||
// it means the property is invalid.
|
||||
if s[index] != keyValueDelimiter[0] {
|
||||
return p, ok
|
||||
return fields, ok
|
||||
}
|
||||
|
||||
// Attempting to parse the value.
|
||||
@@ -769,23 +832,59 @@ func parsePropertyInternal(s string) (p Property, ok bool) {
|
||||
// we have not reached the end, it means the property is
|
||||
// invalid, something like: " key = value value1".
|
||||
if index != len(s) {
|
||||
return p, ok
|
||||
return fields, ok
|
||||
}
|
||||
rawVal := s[valueStart:valueEnd]
|
||||
if !validPercentEncoding(rawVal) {
|
||||
return fields, ok
|
||||
}
|
||||
|
||||
fields.key = s[keyStart:keyEnd]
|
||||
fields.rawValue = rawVal
|
||||
fields.hasValue = true
|
||||
return fields, true
|
||||
}
|
||||
|
||||
func validPercentEncoding(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] != '%' {
|
||||
continue
|
||||
}
|
||||
if i+2 >= len(s) || !isHex(s[i+1]) || !isHex(s[i+2]) {
|
||||
return false
|
||||
}
|
||||
i += 2
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isHex(c byte) bool {
|
||||
return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
|
||||
}
|
||||
|
||||
// parsePropertyInternal attempts to decode a Property from the passed string.
|
||||
// It follows the spec at https://www.w3.org/TR/baggage/#definition.
|
||||
func parsePropertyInternal(s string) (p Property, ok bool) {
|
||||
fields, ok := parsePropertyFields(s)
|
||||
if !ok {
|
||||
return p, false
|
||||
}
|
||||
if !fields.hasValue {
|
||||
p.key = fields.key
|
||||
return p, true
|
||||
}
|
||||
|
||||
// Decode a percent-encoded value.
|
||||
rawVal := s[valueStart:valueEnd]
|
||||
unescapeVal, err := url.PathUnescape(rawVal)
|
||||
unescapeVal, err := url.PathUnescape(fields.rawValue)
|
||||
if err != nil {
|
||||
return p, ok
|
||||
return p, false
|
||||
}
|
||||
value := replaceInvalidUTF8Sequences(len(rawVal), unescapeVal)
|
||||
value := replaceInvalidUTF8Sequences(len(fields.rawValue), unescapeVal)
|
||||
|
||||
ok = true
|
||||
p.key = s[keyStart:keyEnd]
|
||||
p.key = fields.key
|
||||
p.hasValue = true
|
||||
|
||||
p.value = value
|
||||
return p, ok
|
||||
return p, true
|
||||
}
|
||||
|
||||
func skipSpace(s string, offset int) int {
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ const (
|
||||
maxCode = 3
|
||||
)
|
||||
|
||||
// Code is an 32-bit representation of a status state.
|
||||
// Code is a 32-bit representation of a status state.
|
||||
type Code uint32
|
||||
|
||||
var codeToStr = map[Code]string{
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# This is a renovate-friendly source of Docker images.
|
||||
FROM python:3.13.6-slim-bullseye@sha256:e98b521460ee75bca92175c16247bdf7275637a8faaeb2bcfa19d879ae5c4b9a AS python
|
||||
FROM otel/weaver:v0.25.1@sha256:9ad46ca9cd4fa5974b121f886aa3e9946a8ef8ea905001a96c018d21f9db87ca AS weaver
|
||||
FROM otel/weaver:v0.26.1@sha256:9094862c0ab261bdbcb079bb981f9a573b3659b130a6d2ab8616eca6ba37aaec AS weaver
|
||||
FROM avtodev/markdown-lint:v1@sha256:6aeedc2f49138ce7a1cd0adffc1b1c0321b841dc2102408967d9301c031949ee AS markdown
|
||||
Generated
Vendored
+2
@@ -9,6 +9,8 @@ import (
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
)
|
||||
|
||||
// InstrumentationScope transforms il into an OTLP InstrumentationScope,
|
||||
// returning nil if il is the zero value.
|
||||
func InstrumentationScope(il instrumentation.Scope) *commonpb.InstrumentationScope {
|
||||
if il == (instrumentation.Scope{}) {
|
||||
return nil
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@ package otlptrace
|
||||
|
||||
// Version is the current release version of the OpenTelemetry OTLP trace exporter in use.
|
||||
func Version() string {
|
||||
return "1.46.0"
|
||||
return "1.47.0"
|
||||
}
|
||||
+26
-3
@@ -16,12 +16,35 @@ package baggage
|
||||
// but OpenTelemetry does not, therefore, this is represented as a map.
|
||||
type List map[string]Item
|
||||
|
||||
// Item is the value and metadata properties part of a list-member.
|
||||
// Item is the value and metadata or properties part of a list-member.
|
||||
// Metadata and properties are mutually exclusive representations.
|
||||
type Item struct {
|
||||
Value string
|
||||
Properties []Property
|
||||
value string
|
||||
metadata string
|
||||
properties []Property
|
||||
}
|
||||
|
||||
// NewItemWithMetadata returns an Item with opaque W3C metadata.
|
||||
func NewItemWithMetadata(value, metadata string) Item {
|
||||
return Item{value: value, metadata: metadata}
|
||||
}
|
||||
|
||||
// NewItemWithProperties returns an Item with materialized properties.
|
||||
func NewItemWithProperties(value string, properties []Property) Item {
|
||||
return Item{value: value, properties: properties}
|
||||
}
|
||||
|
||||
// Value returns the value of i.
|
||||
func (i Item) Value() string { return i.value }
|
||||
|
||||
// Metadata returns the opaque W3C metadata of i. It is empty for an Item
|
||||
// created with properties.
|
||||
func (i Item) Metadata() string { return i.metadata }
|
||||
|
||||
// Properties returns the materialized properties of i. It is nil for an Item
|
||||
// created with metadata.
|
||||
func (i Item) Properties() []Property { return i.properties }
|
||||
|
||||
// Property is a metadata entry for a list-member.
|
||||
type Property struct {
|
||||
Key, Value string
|
||||
|
||||
+5
@@ -21,6 +21,9 @@ type ErrorHandler interface {
|
||||
Handle(error)
|
||||
}
|
||||
|
||||
// ErrDelegator is an ErrorHandler that forwards errors to a delegate
|
||||
// ErrorHandler set with setDelegate. Before a delegate is set, it logs
|
||||
// errors to STDERR.
|
||||
type ErrDelegator struct {
|
||||
delegate atomic.Pointer[ErrorHandler]
|
||||
}
|
||||
@@ -28,6 +31,8 @@ type ErrDelegator struct {
|
||||
// Compile-time check that delegator implements ErrorHandler.
|
||||
var _ ErrorHandler = (*ErrDelegator)(nil)
|
||||
|
||||
// Handle handles err by forwarding it to the configured delegate, or
|
||||
// logging it to STDERR if no delegate is set.
|
||||
func (d *ErrDelegator) Handle(err error) {
|
||||
if eh := d.delegate.Load(); eh != nil {
|
||||
(*eh).Handle(err)
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/log"
|
||||
"go.opentelemetry.io/otel/log/embedded"
|
||||
)
|
||||
|
||||
type loggerProvider struct {
|
||||
embedded.LoggerProvider
|
||||
|
||||
mu sync.Mutex
|
||||
loggers map[il]*logger
|
||||
delegate log.LoggerProvider
|
||||
}
|
||||
|
||||
// This is a compile-time guarantee that loggerProvider implements LoggerProvider.
|
||||
var _ log.LoggerProvider = (*loggerProvider)(nil)
|
||||
|
||||
func (p *loggerProvider) Logger(name string, options ...log.LoggerOption) log.Logger {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
if p.delegate != nil {
|
||||
return p.delegate.Logger(name, options...)
|
||||
}
|
||||
|
||||
cfg := log.NewLoggerConfig(options...)
|
||||
key := il{
|
||||
name: name,
|
||||
version: cfg.InstrumentationVersion(),
|
||||
schema: cfg.SchemaURL(),
|
||||
attrs: cfg.InstrumentationAttributes(),
|
||||
}
|
||||
|
||||
if p.loggers == nil {
|
||||
l := &logger{name: name, options: options}
|
||||
p.loggers = map[il]*logger{key: l}
|
||||
return l
|
||||
}
|
||||
|
||||
if l, ok := p.loggers[key]; ok {
|
||||
return l
|
||||
}
|
||||
|
||||
l := &logger{name: name, options: options}
|
||||
p.loggers[key] = l
|
||||
return l
|
||||
}
|
||||
|
||||
func (p *loggerProvider) setDelegate(provider log.LoggerProvider) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
p.delegate = provider
|
||||
for _, l := range p.loggers {
|
||||
l.setDelegate(provider)
|
||||
}
|
||||
p.loggers = nil // Only set logger delegates once.
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
embedded.Logger
|
||||
|
||||
name string
|
||||
options []log.LoggerOption
|
||||
|
||||
delegate atomic.Value // log.Logger
|
||||
}
|
||||
|
||||
// This is a compile-time guarantee that logger implements Logger.
|
||||
var _ log.Logger = (*logger)(nil)
|
||||
|
||||
func (l *logger) Emit(ctx context.Context, r log.Record) {
|
||||
if del, ok := l.delegate.Load().(log.Logger); ok {
|
||||
del.Emit(ctx, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) Enabled(ctx context.Context, param log.EnabledParameters) bool {
|
||||
var enabled bool
|
||||
if del, ok := l.delegate.Load().(log.Logger); ok {
|
||||
enabled = del.Enabled(ctx, param)
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func (l *logger) setDelegate(provider log.LoggerProvider) {
|
||||
l.delegate.Store(provider.Logger(l.name, l.options...))
|
||||
}
|
||||
+42
-3
@@ -9,6 +9,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/errorhandler"
|
||||
"go.opentelemetry.io/otel/log"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
@@ -26,16 +27,22 @@ type (
|
||||
meterProviderHolder struct {
|
||||
mp metric.MeterProvider
|
||||
}
|
||||
|
||||
loggerProviderHolder struct {
|
||||
provider log.LoggerProvider
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
globalTracer = defaultTracerValue()
|
||||
globalPropagators = defaultPropagatorsValue()
|
||||
globalMeterProvider = defaultMeterProvider()
|
||||
globalTracer = defaultTracerValue()
|
||||
globalPropagators = defaultPropagatorsValue()
|
||||
globalMeterProvider = defaultMeterProvider()
|
||||
globalLoggerProvider = defaultLoggerProvider()
|
||||
|
||||
delegateTraceOnce sync.Once
|
||||
delegateTextMapPropagatorOnce sync.Once
|
||||
delegateMeterOnce sync.Once
|
||||
delegateLoggerOnce sync.Once
|
||||
)
|
||||
|
||||
// GetErrorHandler returns the global ErrorHandler instance.
|
||||
@@ -150,6 +157,32 @@ func SetMeterProvider(mp metric.MeterProvider) {
|
||||
globalMeterProvider.Store(meterProviderHolder{mp: mp})
|
||||
}
|
||||
|
||||
// LoggerProvider is the internal implementation for global.LoggerProvider.
|
||||
func LoggerProvider() log.LoggerProvider {
|
||||
return globalLoggerProvider.Load().(loggerProviderHolder).provider
|
||||
}
|
||||
|
||||
// SetLoggerProvider is the internal implementation for global.SetLoggerProvider.
|
||||
func SetLoggerProvider(provider log.LoggerProvider) {
|
||||
current := LoggerProvider()
|
||||
if _, cOk := current.(*loggerProvider); cOk {
|
||||
if _, lpOk := provider.(*loggerProvider); lpOk && current == provider {
|
||||
Error(
|
||||
errors.New("no delegate configured in logger provider"),
|
||||
"Setting logger provider to its current value. No delegate will be configured",
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
delegateLoggerOnce.Do(func() {
|
||||
if def, ok := current.(*loggerProvider); ok {
|
||||
def.setDelegate(provider)
|
||||
}
|
||||
})
|
||||
globalLoggerProvider.Store(loggerProviderHolder{provider: provider})
|
||||
}
|
||||
|
||||
func defaultTracerValue() *atomic.Value {
|
||||
v := &atomic.Value{}
|
||||
v.Store(tracerProviderHolder{tp: &tracerProvider{}})
|
||||
@@ -167,3 +200,9 @@ func defaultMeterProvider() *atomic.Value {
|
||||
v.Store(meterProviderHolder{mp: &meterProvider{}})
|
||||
return v
|
||||
}
|
||||
|
||||
func defaultLoggerProvider() *atomic.Value {
|
||||
v := &atomic.Value{}
|
||||
v.Store(loggerProviderHolder{provider: &loggerProvider{}})
|
||||
return v
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otel
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
"go.opentelemetry.io/otel/log"
|
||||
)
|
||||
|
||||
// Logger returns a [log.Logger] configured with the provided name and options
|
||||
// from the globally configured [log.LoggerProvider].
|
||||
//
|
||||
// If this is called before a global LoggerProvider is configured, the returned
|
||||
// Logger will be a No-Op implementation of a Logger. When a global
|
||||
// LoggerProvider is registered for the first time, the returned Logger is
|
||||
// updated in place to report to this new LoggerProvider. There is no need to
|
||||
// call this function again for an updated instance.
|
||||
//
|
||||
// This is a convenience function. It is equivalent to:
|
||||
//
|
||||
// GetLoggerProvider().Logger(name, options...)
|
||||
func Logger(name string, options ...log.LoggerOption) log.Logger {
|
||||
return GetLoggerProvider().Logger(name, options...)
|
||||
}
|
||||
|
||||
// GetLoggerProvider returns the globally configured [log.LoggerProvider].
|
||||
//
|
||||
// If a global LoggerProvider has not been configured with [SetLoggerProvider],
|
||||
// the returned LoggerProvider will be a No-Op implementation. When
|
||||
// a global LoggerProvider is registered for the first time, the returned
|
||||
// LoggerProvider and all Loggers it has created are updated in place. There is
|
||||
// no need to call this function again for an updated instance.
|
||||
func GetLoggerProvider() log.LoggerProvider {
|
||||
return global.LoggerProvider()
|
||||
}
|
||||
|
||||
// SetLoggerProvider configures provider as the global [log.LoggerProvider].
|
||||
func SetLoggerProvider(provider log.LoggerProvider) {
|
||||
global.SetLoggerProvider(provider)
|
||||
}
|
||||
+566
@@ -0,0 +1,566 @@
|
||||
# Logs API
|
||||
|
||||
## Abstract
|
||||
|
||||
`go.opentelemetry.io/otel/log` provides
|
||||
[Logs API](https://opentelemetry.io/docs/specs/otel/logs/api/).
|
||||
|
||||
The prototype was created in
|
||||
[#4725](https://github.com/open-telemetry/opentelemetry-go/pull/4725).
|
||||
|
||||
## Background
|
||||
|
||||
The key challenge is to create a performant API compliant with the [specification](https://opentelemetry.io/docs/specs/otel/logs/api/)
|
||||
with an intuitive and user friendly design.
|
||||
Performance is seen as one of the most important characteristics of logging libraries in Go.
|
||||
|
||||
## Design
|
||||
|
||||
This proposed design aims to:
|
||||
|
||||
- be specification compliant,
|
||||
- be similar to Trace and Metrics API,
|
||||
- take advantage of both OpenTelemetry and `slog` experience to achieve acceptable performance.
|
||||
|
||||
### Module structure
|
||||
|
||||
The API is published as a single `go.opentelemetry.io/otel/log` Go module.
|
||||
|
||||
The package structure is similar to Trace API and Metrics API.
|
||||
The Go module consists of the following packages:
|
||||
|
||||
- `go.opentelemetry.io/otel/log`
|
||||
- `go.opentelemetry.io/otel/log/embedded`
|
||||
- `go.opentelemetry.io/otel/log/logtest`
|
||||
- `go.opentelemetry.io/otel/log/noop`
|
||||
|
||||
Rejected alternative:
|
||||
|
||||
- [Reuse slog](#reuse-slog)
|
||||
|
||||
### LoggerProvider
|
||||
|
||||
The [`LoggerProvider` abstraction](https://opentelemetry.io/docs/specs/otel/logs/api/#loggerprovider)
|
||||
is defined as `LoggerProvider` interface in [provider.go](provider.go).
|
||||
|
||||
The specification may add new operations to `LoggerProvider`.
|
||||
The interface may have methods added without a package major version bump.
|
||||
This embeds `embedded.LoggerProvider` to help inform an API implementation
|
||||
author about this non-standard API evolution.
|
||||
This approach is already used in Trace API and Metrics API.
|
||||
|
||||
#### LoggerProvider.Logger
|
||||
|
||||
The `Logger` method implements the [`Get a Logger` operation](https://opentelemetry.io/docs/specs/otel/logs/api/#get-a-logger).
|
||||
|
||||
The required `name` parameter is accepted as a `string` method argument.
|
||||
|
||||
The `LoggerOption` options are defined to support optional parameters.
|
||||
|
||||
Implementation requirements:
|
||||
|
||||
- The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/api/#concurrency-requirements)
|
||||
the method to be safe to be called concurrently.
|
||||
|
||||
- If the passed name is empty, this should be reported as invalid as specified
|
||||
by the [Logs SDK specification](https://opentelemetry.io/docs/specs/otel/logs/sdk/#logger-creation).
|
||||
The method should still use it as the instrumentation scope name and return
|
||||
a working logger.
|
||||
|
||||
`Logger` can be extended by adding new `LoggerOption` options
|
||||
and adding new exported fields to the `LoggerConfig` struct.
|
||||
This design is already used in Trace API for getting tracers
|
||||
and in Metrics API for getting meters.
|
||||
|
||||
Rejected alternative:
|
||||
|
||||
- [Passing struct as parameter to LoggerProvider.Logger](#passing-struct-as-parameter-to-loggerproviderlogger).
|
||||
|
||||
### Logger
|
||||
|
||||
The [`Logger` abstraction](https://opentelemetry.io/docs/specs/otel/logs/api/#logger)
|
||||
is defined as `Logger` interface in [logger.go](logger.go).
|
||||
|
||||
The specification may add new operations to `Logger`.
|
||||
The interface may have methods added without a package major version bump.
|
||||
This embeds `embedded.Logger` to help inform an API implementation
|
||||
author about this non-standard API evolution.
|
||||
This approach is already used in Trace API and Metrics API.
|
||||
|
||||
### Logger.Emit
|
||||
|
||||
The `Emit` method implements the [`Emit a LogRecord` operation](https://opentelemetry.io/docs/specs/otel/logs/api/#emit-a-logrecord).
|
||||
|
||||
[`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/)
|
||||
is accepted as a `context.Context` method argument.
|
||||
|
||||
Calls to `Emit` are supposed to be on the hot path.
|
||||
Therefore, in order to reduce the number of heap allocations,
|
||||
the [`LogRecord` abstraction](https://opentelemetry.io/docs/specs/otel/logs/api/#emit-a-logrecord),
|
||||
is defined as `Record` struct in [record.go](record.go).
|
||||
|
||||
[`Timestamp`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-timestamp)
|
||||
is accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) Timestamp() time.Time
|
||||
func (r *Record) SetTimestamp(t time.Time)
|
||||
```
|
||||
|
||||
[`ObservedTimestamp`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-observedtimestamp)
|
||||
is accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) ObservedTimestamp() time.Time
|
||||
func (r *Record) SetObservedTimestamp(t time.Time)
|
||||
```
|
||||
|
||||
[`EventName`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-eventname)
|
||||
is accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) EventName() string
|
||||
func (r *Record) SetEventName(s string)
|
||||
```
|
||||
|
||||
[`SeverityNumber`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber)
|
||||
is accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) Severity() Severity
|
||||
func (r *Record) SetSeverity(s Severity)
|
||||
```
|
||||
|
||||
`Severity` type is defined in [severity.go](severity.go).
|
||||
The constants are are based on
|
||||
[Displaying Severity recommendation](https://opentelemetry.io/docs/specs/otel/logs/data-model/#displaying-severity).
|
||||
Additionally, `Severity[Level]` constants are defined to make the API more readable and user friendly.
|
||||
|
||||
[`SeverityText`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitytext)
|
||||
is accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) SeverityText() string
|
||||
func (r *Record) SetSeverityText(s string)
|
||||
```
|
||||
|
||||
[`Body`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-body)
|
||||
is accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) Body() attribute.Value
|
||||
func (r *Record) SetBody(v attribute.Value)
|
||||
```
|
||||
|
||||
[Log record attributes](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-attributes)
|
||||
are accessed using following methods:
|
||||
|
||||
```go
|
||||
func (r *Record) WalkAttributes(f func(attribute.KeyValue) bool)
|
||||
func (r *Record) AddAttributes(attrs ...attribute.KeyValue)
|
||||
```
|
||||
|
||||
`Record` has a `AttributesLen` method that returns
|
||||
the number of attributes to allow slice preallocation
|
||||
when converting records to a different representation:
|
||||
|
||||
```go
|
||||
func (r *Record) AttributesLen() int
|
||||
```
|
||||
|
||||
The records attributes design and implementation is based on
|
||||
[`slog.Record`](https://pkg.go.dev/log/slog#Record).
|
||||
It allows achieving high-performance access and manipulation of the attributes
|
||||
while keeping the API user friendly.
|
||||
It relieves the user from making his own improvements
|
||||
for reducing the number of allocations when passing attributes.
|
||||
|
||||
Log body and attributes use the common
|
||||
[`attribute.Value`](https://pkg.go.dev/go.opentelemetry.io/otel/attribute#Value)
|
||||
and
|
||||
[`attribute.KeyValue`](https://pkg.go.dev/go.opentelemetry.io/otel/attribute#KeyValue)
|
||||
types.
|
||||
These types cover the Logs Data Model `any` value shape, including empty
|
||||
values, byte slices, generic slices, and maps.
|
||||
Reusing the attribute package keeps the API consistent across signals and
|
||||
avoids maintaining a second value model with conversion helpers.
|
||||
|
||||
The zero value of `attribute.Value` represents an empty body.
|
||||
Log maps use `attribute.MAP`, which may contain duplicate keys when callers
|
||||
construct one that way. Duplicate-key normalization is an SDK policy, not an
|
||||
API behavior.
|
||||
|
||||
The caller must not subsequently mutate the record passed to `Emit`.
|
||||
This would allow the implementation to not clone the record,
|
||||
but simply retain, modify or discard it.
|
||||
The implementation may still choose to clone the record or copy its attributes
|
||||
if it needs to retain or modify it,
|
||||
e.g. in case of asynchronous processing to eliminate the possibility of data races,
|
||||
because the user can technically reuse the record and add new attributes
|
||||
after the call (even when the documentation says that the caller must not do it).
|
||||
|
||||
Implementation requirements:
|
||||
|
||||
- The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/api/#concurrency-requirements)
|
||||
the method to be safe to be called concurrently.
|
||||
|
||||
- The method must not interrupt the record processing if the context is canceled
|
||||
per ["ignoring context cancellation" guideline](../CONTRIBUTING.md#ignoring-context-cancellation).
|
||||
|
||||
- The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/api/#emit-a-logrecord)
|
||||
use the current time as observed timestamp if the passed is empty.
|
||||
|
||||
- The method should handle the trace context passed via `ctx` argument in order to meet the
|
||||
[specification's SDK requirement](https://opentelemetry.io/docs/specs/otel/logs/sdk/#readablelogrecord)
|
||||
to populate the trace context fields from the resolved context.
|
||||
|
||||
`Emit` can be extended by adding new exported fields to the `Record` struct.
|
||||
|
||||
Rejected alternatives:
|
||||
|
||||
- [Record as interface](#record-as-interface)
|
||||
- [Options as parameter to Logger.Emit](#options-as-parameter-to-loggeremit)
|
||||
- [Passing record as pointer to Logger.Emit](#passing-record-as-pointer-to-loggeremit)
|
||||
- [Logger.WithAttributes](#loggerwithattributes)
|
||||
- [Record attributes as slice](#record-attributes-as-slice)
|
||||
- [Use any instead of attribute.Value](#use-any-instead-of-attributevalue)
|
||||
- [Severity type encapsulating number and text](#severity-type-encapsulating-number-and-text)
|
||||
- [Define log-specific value types](#define-log-specific-value-types)
|
||||
- [Mix receiver types for Record](#mix-receiver-types-for-record)
|
||||
- [Add XYZ method to Logger](#add-xyz-method-to-logger)
|
||||
|
||||
### Logger.Enabled
|
||||
|
||||
The `Enabled` method implements the [`Enabled` operation](https://opentelemetry.io/docs/specs/otel/logs/api/#enabled).
|
||||
|
||||
[`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/)
|
||||
is accepted as a `context.Context` method argument.
|
||||
|
||||
Calls to `Enabled` are supposed to be on the hot path and the list of arguments
|
||||
can be extendend in future. Therefore, in order to reduce the number of heap
|
||||
allocations and make it possible to handle new arguments, `Enabled` accepts
|
||||
a `EnabledParameters` struct, defined in [logger.go](logger.go), as the second
|
||||
method argument.
|
||||
|
||||
The `EnabledParameters` uses fields, instead of getters and setters, to allow
|
||||
simpler usage which allows configuring the `EnabledParameters` in the same line
|
||||
where `Enabled` is called.
|
||||
|
||||
### noop package
|
||||
|
||||
The `go.opentelemetry.io/otel/log/noop` package provides
|
||||
[Logs API No-Op Implementation](https://opentelemetry.io/docs/specs/otel/logs/noop/).
|
||||
|
||||
### Trace context correlation
|
||||
|
||||
The bridge implementation should do its best to pass
|
||||
the `ctx` containing the trace context from the caller
|
||||
so it can later be passed via `Logger.Emit`.
|
||||
|
||||
It is not expected that users (caller or bridge implementation) reconstruct
|
||||
a `context.Context`. Reconstructing a `context.Context` with
|
||||
[`trace.ContextWithSpanContext`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#ContextWithSpanContext)
|
||||
and [`trace.NewSpanContext`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#NewSpanContext)
|
||||
would usually involve more memory allocations.
|
||||
|
||||
The logging libraries which have recording methods that accepts `context.Context`,
|
||||
such us [`slog`](https://pkg.go.dev/log/slog),
|
||||
[`logrus`](https://pkg.go.dev/github.com/sirupsen/logrus),
|
||||
[`zerolog`](https://pkg.go.dev/github.com/rs/zerolog),
|
||||
makes passing the trace context trivial.
|
||||
|
||||
However, some libraries do not accept a `context.Context` in their recording methods.
|
||||
Structured logging libraries,
|
||||
such as [`logr`](https://pkg.go.dev/github.com/go-logr/logr)
|
||||
and [`zap`](https://pkg.go.dev/go.uber.org/zap),
|
||||
offer passing `any` type as a log attribute/field.
|
||||
Therefore, their bridge implementations can define a "special" log attributes/field
|
||||
that will be used to capture the trace context.
|
||||
|
||||
[The prototype](https://github.com/open-telemetry/opentelemetry-go/pull/4725)
|
||||
has bridge implementations that handle trace context correlation efficiently.
|
||||
|
||||
## Benchmarking
|
||||
|
||||
The benchmarks take inspiration from [`slog`](https://pkg.go.dev/log/slog),
|
||||
because for the Go team it was also critical to create API that would be fast
|
||||
and interoperable with existing logging packages.[^2][^3]
|
||||
|
||||
The benchmark results can be found in [the prototype](https://github.com/open-telemetry/opentelemetry-go/pull/4725).
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
### Reuse slog
|
||||
|
||||
The API must not be coupled to [`slog`](https://pkg.go.dev/log/slog),
|
||||
nor any other logging library.
|
||||
|
||||
The API needs to evolve orthogonally to `slog`.
|
||||
|
||||
`slog` is not compliant with the [Logs API](https://opentelemetry.io/docs/specs/otel/logs/api/).
|
||||
and we cannot expect the Go team to make `slog` compliant with it.
|
||||
|
||||
The interoperability can be achieved using [a log bridge](https://opentelemetry.io/docs/specs/otel/glossary/#log-appender--bridge).
|
||||
|
||||
You can read more about OpenTelemetry Logs design on [opentelemetry.io](https://opentelemetry.io/docs/concepts/signals/logs/).
|
||||
|
||||
### Record as interface
|
||||
|
||||
`Record` is defined as a `struct` because of the following reasons.
|
||||
|
||||
Log record is a value object without any behavior.
|
||||
It is used as data input for Logger methods.
|
||||
|
||||
The log record resembles the instrument config structs like [metric.Float64CounterConfig](https://pkg.go.dev/go.opentelemetry.io/otel/metric#Float64CounterConfig).
|
||||
|
||||
Using `struct` instead of `interface` improves the performance as e.g.
|
||||
indirect calls are less optimized,
|
||||
usage of interfaces tend to increase heap allocations.[^3]
|
||||
|
||||
### Options as parameter to Logger.Emit
|
||||
|
||||
One of the initial ideas was to have:
|
||||
|
||||
```go
|
||||
type Logger interface{
|
||||
embedded.Logger
|
||||
Emit(ctx context.Context, options ...RecordOption)
|
||||
}
|
||||
```
|
||||
|
||||
The main reason was that design would be similar
|
||||
to the [Meter API](https://pkg.go.dev/go.opentelemetry.io/otel/metric#Meter)
|
||||
for creating instruments.
|
||||
|
||||
However, passing `Record` directly, instead of using options,
|
||||
is more performant as it reduces heap allocations.[^4]
|
||||
|
||||
Another advantage of passing `Record` is that API would not have functions like `NewRecord(options...)`,
|
||||
which would be used by the SDK and not by the users.
|
||||
|
||||
Finally, the definition would be similar to [`slog.Handler.Handle`](https://pkg.go.dev/log/slog#Handler)
|
||||
that was designed to provide optimization opportunities.[^2]
|
||||
|
||||
### Passing record as pointer to Logger.Emit
|
||||
|
||||
So far the benchmarks do not show differences that would
|
||||
favor passing the record via pointer (and vice versa).
|
||||
|
||||
Passing via value feels safer because of the following reasons.
|
||||
|
||||
The user would not be able to pass `nil`.
|
||||
Therefore, it reduces the possibility to have a nil pointer dereference.
|
||||
|
||||
It should reduce the possibility of a heap allocation.
|
||||
|
||||
It follows the design of [`slog.Handler`](https://pkg.go.dev/log/slog#Handler).
|
||||
|
||||
If follows one of Google's Go Style Decisions
|
||||
to prefer [passing values](https://google.github.io/styleguide/go/decisions#pass-values).
|
||||
|
||||
### Passing struct as parameter to LoggerProvider.Logger
|
||||
|
||||
Similarly to `Logger.Emit`, we could have something like:
|
||||
|
||||
```go
|
||||
type LoggerProvider interface{
|
||||
embedded.LoggerProvider
|
||||
Logger(name string, config LoggerConfig)
|
||||
}
|
||||
```
|
||||
|
||||
The drawback of this idea would be that this would be
|
||||
a different design from Trace and Metrics API.
|
||||
|
||||
The performance of acquiring a logger is not as critical
|
||||
as the performance of emitting a log record. While a single
|
||||
HTTP/RPC handler could write hundreds of logs, it should not
|
||||
create a new logger for each log entry.
|
||||
The bridge implementation should reuse loggers whenever possible.
|
||||
|
||||
### Logger.WithAttributes
|
||||
|
||||
We could add `WithAttributes` to the `Logger` interface.
|
||||
Then `Record` could be a simple struct with only exported fields.
|
||||
The idea was that the SDK would implement the performance improvements
|
||||
instead of doing it in the API.
|
||||
This would allow having different optimization strategies.
|
||||
|
||||
During the analysis[^5], it occurred that the main problem of this proposal
|
||||
is that the variadic slice passed to an interface method is always heap allocated.
|
||||
|
||||
Moreover, the logger returned by `WithAttribute` was allocated on the heap.
|
||||
|
||||
Lastly, the proposal was not specification compliant.
|
||||
|
||||
### Record attributes as slice
|
||||
|
||||
One of the proposals[^6] was to have `Record` as a simple struct:
|
||||
|
||||
```go
|
||||
type Record struct {
|
||||
Timestamp time.Time
|
||||
ObservedTimestamp time.Time
|
||||
EventName string
|
||||
Severity Severity
|
||||
SeverityText string
|
||||
Body Value
|
||||
Attributes []KeyValue
|
||||
}
|
||||
```
|
||||
|
||||
The bridge implementations could use [`sync.Pool`](https://pkg.go.dev/sync#Pool)
|
||||
for reducing the number of allocations when passing attributes.
|
||||
|
||||
The benchmarks results were better.
|
||||
|
||||
In such a design, most bridges would have a `sync.Pool`
|
||||
to reduce the number of heap allocations.
|
||||
However, the `sync.Pool` will not work correctly with API implementations
|
||||
that would take ownership of the record
|
||||
(e.g. implementations that do not copy records for asynchronous processing).
|
||||
The current design, even in case of improper API implementation,
|
||||
has lower chances of encountering a bug as most bridges would
|
||||
create a record, pass it, and forget about it.
|
||||
|
||||
For reference, here is the reason why `slog` does not use `sync.Pool`[^3]
|
||||
as well:
|
||||
|
||||
> We can use a sync pool for records though we decided not to.
|
||||
You can but it's a bad idea for us. Why?
|
||||
Because users have control of Records.
|
||||
Handler writers can get their hands on a record
|
||||
and we'd have to ask them to free it
|
||||
or try to free it magically at some some point.
|
||||
But either way, they could get themselves in trouble by freeing it twice
|
||||
or holding on to one after they free it.
|
||||
That's a use after free bug and that's why `zerolog` was problematic for us.
|
||||
`zerolog` as as part of its speed exposes a pool allocated value to users
|
||||
if you use `zerolog` the normal way, that you'll see in all the examples,
|
||||
you will never encounter a problem.
|
||||
But if you do something a little out of the ordinary you can get
|
||||
use after free bugs and we just didn't want to put that in the standard library.
|
||||
|
||||
Therefore, we decided to not follow the proposal as it is
|
||||
less user friendly (users and bridges would use e.g. a `sync.Pool` to reduce
|
||||
the number of heap allocation), less safe (more prone to use after free bugs
|
||||
and race conditions), and the benchmark differences were not significant.
|
||||
|
||||
### Use any instead of attribute.Value
|
||||
|
||||
[Logs Data Model](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-body)
|
||||
defines Body to be `any`.
|
||||
One could propose to define `Body` (and attribute values) as `any`
|
||||
instead of using `attribute.Value`.
|
||||
|
||||
First of all, [`any` type defined in the specification](https://opentelemetry.io/docs/specs/otel/logs/data-model/#type-any)
|
||||
is not the same as `any` (`interface{}`) in Go.
|
||||
|
||||
Moreover, using `any` as a field would decrease the performance.[^7]
|
||||
|
||||
Using `attribute.Value` preserves a typed, allocation-conscious representation
|
||||
of the Logs Data Model `any` values while avoiding unconstrained `interface{}`
|
||||
handling in bridge implementations.
|
||||
|
||||
### Severity type encapsulating number and text
|
||||
|
||||
We could combine severity into a single field defining a type:
|
||||
|
||||
```go
|
||||
type Severity struct {
|
||||
Number SeverityNumber
|
||||
Text string
|
||||
}
|
||||
```
|
||||
|
||||
However, the [Logs Data Model](https://opentelemetry.io/docs/specs/otel/logs/data-model/#log-and-event-record-definition)
|
||||
define it as independent fields.
|
||||
It should be more user friendly to have them separated.
|
||||
Especially when having getter and setter methods, setting one value
|
||||
when the other is already set would be unpleasant.
|
||||
|
||||
### Define log-specific value types
|
||||
|
||||
The original design defined `Kind`, `Value`, and `KeyValue` in
|
||||
`go.opentelemetry.io/otel/log`.
|
||||
That avoided coupling log bodies to the common attribute package while logs were
|
||||
still exploring structured value support.
|
||||
|
||||
The Logs Data Model and common attribute value model now share the structured
|
||||
`any` shapes needed by Go: empty, bool, int64, float64, string, byte slice,
|
||||
homogeneous slices, generic slices, and maps.
|
||||
The specification direction is to reuse these value shapes across signals.
|
||||
Keeping log-specific types would duplicate API surface, require conversion
|
||||
helpers, and make bridge code choose between two equivalent value models.
|
||||
|
||||
Therefore log records now use `attribute.Value` for body values and
|
||||
`attribute.KeyValue` for attributes and map entries.
|
||||
|
||||
### Mix receiver types for Record
|
||||
|
||||
Methods of [`slog.Record`](https://pkg.go.dev/log/slog#Record)
|
||||
have different receiver types.
|
||||
|
||||
In `log/slog` GitHub issue we can only find that the reason is:[^8]
|
||||
|
||||
>> some receiver of Record struct is by value
|
||||
> Passing Records by value means they incur no heap allocation.
|
||||
> That improves performance overall, even though they are copied.
|
||||
|
||||
However, the benchmarks do not show any noticeable differences.[^9]
|
||||
|
||||
The compiler is smart-enough to not make a heap allocation for any of these methods.
|
||||
The use of a pointer receiver does not cause any heap allocation.
|
||||
From Go FAQ:[^10]
|
||||
|
||||
> In the current compilers, if a variable has its address taken,
|
||||
> that variable is a candidate for allocation on the heap.
|
||||
> However, a basic escape analysis recognizes some cases
|
||||
> when such variables will not live past the return from the function
|
||||
> and can reside on the stack.
|
||||
|
||||
The [Understanding Allocations: the Stack and the Heap](https://www.youtube.com/watch?v=ZMZpH4yT7M0)
|
||||
presentation by Jacob Walker describes the escape analysis with details.
|
||||
|
||||
Moreover, also from Go FAQ:[^10]
|
||||
|
||||
> Also, if a local variable is very large,
|
||||
> it might make more sense to store it on the heap rather than the stack.
|
||||
|
||||
Therefore, even if we use a value receiver and the value is very large
|
||||
it may be heap allocated.
|
||||
|
||||
Both [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments#receiver-type)
|
||||
and [Google's Go Style Decisions](https://google.github.io/styleguide/go/decisions#receiver-type)
|
||||
highly recommend making the methods for a type either all pointer methods
|
||||
or all value methods. Google's Go Style Decisions even goes further and says:
|
||||
|
||||
> There is a lot of misinformation about whether passing a value or a pointer
|
||||
> to a function can affect performance.
|
||||
> The compiler can choose to pass pointers to values on the stack
|
||||
> as well as copying values on the stack,
|
||||
> but these considerations should not outweigh the readability
|
||||
> and correctness of the code in most circumstances.
|
||||
> When the performance does matter, it is important to profile both approaches
|
||||
> with a realistic benchmark before deciding that one approach outperforms the other.
|
||||
|
||||
Because, the benchmarks[^9] do not proof any performance difference
|
||||
and the general recommendation is to not mix receiver types,
|
||||
we decided to use pointer receivers for all `Record` methods.
|
||||
|
||||
### Add XYZ method to Logger
|
||||
|
||||
The `Logger` does not have methods like `SetSeverity`, etc.
|
||||
as the Logs API needs to follow (be compliant with)
|
||||
the [specification](https://opentelemetry.io/docs/specs/otel/logs/api/)
|
||||
|
||||
[^1]: [Handle structured body and attributes](https://github.com/pellared/opentelemetry-go/pull/7)
|
||||
[^2]: Jonathan Amsterdam, [The Go Blog: Structured Logging with slog](https://go.dev/blog/slog)
|
||||
[^3]: Jonathan Amsterdam, [GopherCon Europe 2023: A Fast Structured Logging Package](https://www.youtube.com/watch?v=tC4Jt3i62ns)
|
||||
[^4]: [Emit definition discussion with benchmarks](https://github.com/open-telemetry/opentelemetry-go/pull/4725#discussion_r1400869566)
|
||||
[^5]: [Logger.WithAttributes analysis](https://github.com/pellared/opentelemetry-go/pull/3)
|
||||
[^6]: [Record attributes as field and use sync.Pool for reducing allocations](https://github.com/pellared/opentelemetry-go/pull/4) and [Record attributes based on slog.Record](https://github.com/pellared/opentelemetry-go/pull/6)
|
||||
[^7]: [Record.Body as any](https://github.com/pellared/opentelemetry-go/pull/5)
|
||||
[^8]: [log/slog: structured, leveled logging](https://github.com/golang/go/issues/56345#issuecomment-1302563756)
|
||||
[^9]: [Record with pointer receivers only](https://github.com/pellared/opentelemetry-go/pull/8)
|
||||
[^10]: [Go FAQ: Stack or heap](https://go.dev/doc/faq#stack_or_heap)
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# Log API
|
||||
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel/log)
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
Package log provides the OpenTelemetry Logs API.
|
||||
|
||||
This API is separate from its implementation, so the instrumentation built
|
||||
from it is reusable. See [go.opentelemetry.io/otel/sdk/log] for the official
|
||||
OpenTelemetry implementation of this API.
|
||||
|
||||
The log package provides the OpenTelemetry Logs API, which serves as a standard
|
||||
interface for generating and managing log records within the OpenTelemetry ecosystem.
|
||||
This package allows users to emit LogRecords, enabling structured, context-rich logging
|
||||
that can be easily integrated with observability tools. It ensures that log data is captured
|
||||
in a way that is consistent with OpenTelemetry's data model.
|
||||
|
||||
This package can be used to create bridges between existing logging libraries and OpenTelemetry.
|
||||
Log bridges allow existing logging setups to be integrated with OpenTelemetry.
|
||||
Log bridges can be found in the [registry].
|
||||
|
||||
# API Implementations
|
||||
|
||||
This package does not conform to the standard Go versioning policy; all of its
|
||||
interfaces may have methods added to them without a package major version bump.
|
||||
This non-standard API evolution could surprise an uninformed implementation
|
||||
author. They could unknowingly build their implementation in a way that would
|
||||
result in a runtime panic for their users who update to the new API.
|
||||
|
||||
The API is designed to help inform an instrumentation author about this
|
||||
non-standard API evolution. It requires them to choose a default behavior for
|
||||
unimplemented interface methods. There are three behavior choices they can
|
||||
make:
|
||||
|
||||
- Compilation failure
|
||||
- Panic
|
||||
- Default to another implementation
|
||||
|
||||
All interfaces in this API embed a corresponding interface from
|
||||
[go.opentelemetry.io/otel/log/embedded]. If an author wants the default
|
||||
behavior of their implementations to be a compilation failure, signaling to
|
||||
their users that they need to update to the latest version of that implementation,
|
||||
they need to embed the corresponding interface from
|
||||
[go.opentelemetry.io/otel/log/embedded] in their implementation. For example,
|
||||
|
||||
import "go.opentelemetry.io/otel/log/embedded"
|
||||
|
||||
type LoggerProvider struct {
|
||||
embedded.LoggerProvider
|
||||
// ...
|
||||
}
|
||||
|
||||
If an author wants the default behavior of their implementations to panic,
|
||||
they need to embed the API interface directly.
|
||||
|
||||
import "go.opentelemetry.io/otel/log"
|
||||
|
||||
type LoggerProvider struct {
|
||||
log.LoggerProvider
|
||||
// ...
|
||||
}
|
||||
|
||||
This is not a recommended behavior as it could lead to publishing packages that
|
||||
contain runtime panics when users update other packages that use newer versions
|
||||
of [go.opentelemetry.io/otel/log].
|
||||
|
||||
Finally, an author can embed another implementation in theirs. The embedded
|
||||
implementation will be used for methods not defined by the author. For example,
|
||||
an author who wants to default to silently dropping the call can use
|
||||
[go.opentelemetry.io/otel/log/noop]:
|
||||
|
||||
import "go.opentelemetry.io/otel/log/noop"
|
||||
|
||||
type LoggerProvider struct {
|
||||
noop.LoggerProvider
|
||||
// ...
|
||||
}
|
||||
|
||||
It is strongly recommended that authors only embed
|
||||
go.opentelemetry.io/otel/log/noop if they choose this default behavior. That
|
||||
implementation is the only one OpenTelemetry authors can guarantee will fully
|
||||
implement all the API interfaces when a user updates their API.
|
||||
|
||||
[registry]: https://opentelemetry.io/ecosystem/registry/?language=go&component=log-bridge
|
||||
*/
|
||||
package log
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# Log Embedded
|
||||
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel/log/embedded)
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package embedded provides interfaces embedded within the [OpenTelemetry Logs
|
||||
// Bridge API].
|
||||
//
|
||||
// Implementers of the [OpenTelemetry Logs API] can embed the relevant
|
||||
// type from this package into their implementation directly. Doing so will
|
||||
// result in a compilation error for users when the [OpenTelemetry Logs Bridge
|
||||
// API] is extended (which is something that can happen without a major version
|
||||
// bump of the API package).
|
||||
//
|
||||
// [OpenTelemetry Logs API]: https://pkg.go.dev/go.opentelemetry.io/otel/log
|
||||
package embedded
|
||||
|
||||
// LoggerProvider is embedded in the [Logs API LoggerProvider].
|
||||
//
|
||||
// Embed this interface in your implementation of the [Logs API
|
||||
// LoggerProvider] if you want users to experience a compilation error when the
|
||||
// [Logs Bridge API LoggerProvider] interface is extended (which is something
|
||||
// that can happen without a major version bump of the API package). This error
|
||||
// signals that they need to update to your latest implementation.
|
||||
//
|
||||
// [Logs API LoggerProvider]: https://pkg.go.dev/go.opentelemetry.io/otel/log#LoggerProvider
|
||||
type LoggerProvider interface{ loggerProvider() }
|
||||
|
||||
// Logger is embedded in the [Logs API Logger].
|
||||
//
|
||||
// Embed this interface in your implementation of the [Logs API Logger]
|
||||
// if you want users to experience a compilation error when the [Logs API
|
||||
// Logger] interface is extended (which is something that can happen without a
|
||||
// major version bump of the API package). This error signals that they need to
|
||||
// update to your latest implementation.
|
||||
//
|
||||
// [Logs API Logger]: https://pkg.go.dev/go.opentelemetry.io/otel/log#Logger
|
||||
type Logger interface{ logger() }
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/log/embedded"
|
||||
)
|
||||
|
||||
// Logger emits log records.
|
||||
//
|
||||
// Warning: Methods may be added to this interface in minor releases. See
|
||||
// package documentation on API implementation for information on how to set
|
||||
// the default behavior for unimplemented methods.
|
||||
type Logger interface {
|
||||
// Users of the interface can ignore this. This embedded type is only used
|
||||
// by implementations of this interface. See the "API Implementations"
|
||||
// section of the package documentation for more information.
|
||||
embedded.Logger
|
||||
|
||||
// Emit emits a log record.
|
||||
//
|
||||
// The record may be held by the implementation. Callers should not mutate
|
||||
// the record after it is passed.
|
||||
//
|
||||
// Implementations of this method need to be safe for a user to call
|
||||
// concurrently.
|
||||
Emit(ctx context.Context, record Record)
|
||||
|
||||
// Enabled reports whether the Logger emits for the given context and
|
||||
// param.
|
||||
//
|
||||
// Calling Enabled is optional. It is not required before calling
|
||||
// [Logger.Emit].
|
||||
//
|
||||
// Enabled is useful when constructing a [Record] is expensive. A caller can
|
||||
// call Enabled first and skip record construction when it returns false.
|
||||
// When constructing the Record is inexpensive, a caller can emit it
|
||||
// directly.
|
||||
//
|
||||
// The returned value is not static and may change over time. A cached value
|
||||
// can become stale.
|
||||
//
|
||||
// The passed param is likely to contain only partial information about a
|
||||
// record (e.g., a param with only the Severity set).
|
||||
// If a Logger needs more information than is provided, it
|
||||
// is said to be in an indeterminate state (see below).
|
||||
//
|
||||
// The returned value is true if the Logger emits for the provided context
|
||||
// and param, and false if the Logger does not emit. The returned value may be
|
||||
// true or false in an indeterminate state.
|
||||
// An implementation should default to returning true for an indeterminate
|
||||
// state, but may return false if there are valid reasons to do so in
|
||||
// particular circumstances (e.g., performance or correctness).
|
||||
//
|
||||
// The param should not be held by the implementation. A copy should be
|
||||
// made if the param needs to be held after the call returns.
|
||||
//
|
||||
// Implementations of this method need to be safe for a user to call
|
||||
// concurrently.
|
||||
Enabled(ctx context.Context, param EnabledParameters) bool
|
||||
}
|
||||
|
||||
// LoggerOption applies configuration options to a [Logger].
|
||||
type LoggerOption interface {
|
||||
// applyLogger applies a LoggerOption to a LoggerConfig.
|
||||
applyLogger(LoggerConfig) LoggerConfig
|
||||
}
|
||||
|
||||
// LoggerConfig contains options for a [Logger].
|
||||
type LoggerConfig struct {
|
||||
// Ensure forward compatibility by explicitly making this not comparable.
|
||||
noCmp [0]func() //nolint: unused // This is indeed used.
|
||||
|
||||
version string
|
||||
schemaURL string
|
||||
attrs attribute.Set
|
||||
}
|
||||
|
||||
type experimentalOption interface {
|
||||
Experimental()
|
||||
}
|
||||
|
||||
// NewLoggerConfig returns a new [LoggerConfig] with all the options applied.
|
||||
func NewLoggerConfig(options ...LoggerOption) LoggerConfig {
|
||||
var c LoggerConfig
|
||||
for _, opt := range options {
|
||||
if _, ok := opt.(experimentalOption); ok {
|
||||
continue
|
||||
}
|
||||
c = opt.applyLogger(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// InstrumentationVersion returns the version of the library providing
|
||||
// instrumentation.
|
||||
func (cfg LoggerConfig) InstrumentationVersion() string {
|
||||
return cfg.version
|
||||
}
|
||||
|
||||
// InstrumentationAttributes returns the attributes associated with the library
|
||||
// providing instrumentation.
|
||||
func (cfg LoggerConfig) InstrumentationAttributes() attribute.Set {
|
||||
return cfg.attrs
|
||||
}
|
||||
|
||||
// SchemaURL returns the schema URL of the library providing instrumentation.
|
||||
func (cfg LoggerConfig) SchemaURL() string {
|
||||
return cfg.schemaURL
|
||||
}
|
||||
|
||||
type loggerOptionFunc func(LoggerConfig) LoggerConfig
|
||||
|
||||
func (fn loggerOptionFunc) applyLogger(cfg LoggerConfig) LoggerConfig {
|
||||
return fn(cfg)
|
||||
}
|
||||
|
||||
// WithInstrumentationVersion returns a [LoggerOption] that sets the
|
||||
// instrumentation version of a [Logger].
|
||||
func WithInstrumentationVersion(version string) LoggerOption {
|
||||
return loggerOptionFunc(func(config LoggerConfig) LoggerConfig {
|
||||
config.version = version
|
||||
return config
|
||||
})
|
||||
}
|
||||
|
||||
// mergeSets returns the union of the keys in a and b. For duplicate keys, the
|
||||
// value associated with b is used.
|
||||
func mergeSets(a, b attribute.Set) attribute.Set {
|
||||
// NewMergeIterator uses the first value for any duplicates.
|
||||
iter := attribute.NewMergeIterator(&b, &a)
|
||||
merged := make([]attribute.KeyValue, 0, a.Len()+b.Len())
|
||||
for iter.Next() {
|
||||
merged = append(merged, iter.Attribute())
|
||||
}
|
||||
return attribute.NewSet(merged...)
|
||||
}
|
||||
|
||||
// WithInstrumentationAttributes returns a [LoggerOption] that sets the
|
||||
// instrumentation attributes of a [Logger].
|
||||
//
|
||||
// This is equivalent to calling WithInstrumentationAttributeSet with an
|
||||
// [attribute.Set] created from a clone of the passed attributes.
|
||||
// [WithInstrumentationAttributeSet] is recommended for more control.
|
||||
//
|
||||
// If multiple [WithInstrumentationAttributes] or [WithInstrumentationAttributeSet]
|
||||
// options are passed, the attributes will be merged together in the order
|
||||
// they are passed. For attributes with duplicate keys, the last value passed
|
||||
// will be used.
|
||||
func WithInstrumentationAttributes(attr ...attribute.KeyValue) LoggerOption {
|
||||
set := attribute.NewSet(slices.Clone(attr)...)
|
||||
return WithInstrumentationAttributeSet(set)
|
||||
}
|
||||
|
||||
// WithInstrumentationAttributeSet returns a [LoggerOption] that adds
|
||||
// instrumentation attributes to a [Logger].
|
||||
//
|
||||
// If multiple [WithInstrumentationAttributes] or [WithInstrumentationAttributeSet]
|
||||
// options are passed, the attributes will be merged together in the order
|
||||
// they are passed. For attributes with duplicate keys, the last value passed
|
||||
// will be used.
|
||||
func WithInstrumentationAttributeSet(set attribute.Set) LoggerOption {
|
||||
if set.Len() == 0 {
|
||||
return loggerOptionFunc(func(config LoggerConfig) LoggerConfig {
|
||||
return config
|
||||
})
|
||||
}
|
||||
|
||||
return loggerOptionFunc(func(config LoggerConfig) LoggerConfig {
|
||||
if config.attrs.Len() == 0 {
|
||||
config.attrs = set
|
||||
} else {
|
||||
config.attrs = mergeSets(config.attrs, set)
|
||||
}
|
||||
return config
|
||||
})
|
||||
}
|
||||
|
||||
// WithSchemaURL returns a [LoggerOption] that sets the schema URL for a
|
||||
// [Logger].
|
||||
func WithSchemaURL(schemaURL string) LoggerOption {
|
||||
return loggerOptionFunc(func(config LoggerConfig) LoggerConfig {
|
||||
config.schemaURL = schemaURL
|
||||
return config
|
||||
})
|
||||
}
|
||||
|
||||
// EnabledParameters represents the payload for [Logger.Enabled].
|
||||
type EnabledParameters struct {
|
||||
Severity Severity
|
||||
EventName string
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package log
|
||||
|
||||
import "go.opentelemetry.io/otel/log/embedded"
|
||||
|
||||
// LoggerProvider provides access to [Logger].
|
||||
//
|
||||
// Warning: Methods may be added to this interface in minor releases. See
|
||||
// package documentation on API implementation for information on how to set
|
||||
// the default behavior for unimplemented methods.
|
||||
type LoggerProvider interface {
|
||||
// Users of the interface can ignore this. This embedded type is only used
|
||||
// by implementations of this interface. See the "API Implementations"
|
||||
// section of the package documentation for more information.
|
||||
embedded.LoggerProvider
|
||||
|
||||
// Logger returns a new [Logger] with the provided name and configuration.
|
||||
//
|
||||
// The name needs to uniquely identify the source of logged code. It is
|
||||
// recommended that name be the Go package name of the library using a log
|
||||
// bridge (note: this is not the name of the bridge package). Most
|
||||
// commonly, this means a bridge will need to accept this value from its
|
||||
// users.
|
||||
//
|
||||
// An empty name is invalid. Implementations should retain the empty value as the
|
||||
// instrumentation scope name, return a working Logger, and report the invalid value.
|
||||
//
|
||||
// The version of the package using a bridge can be critical information
|
||||
// to include when logging. The bridge should accept this version
|
||||
// information and use the [WithInstrumentationVersion] option to configure
|
||||
// the Logger appropriately.
|
||||
//
|
||||
// Implementations of this method need to be safe for a user to call
|
||||
// concurrently.
|
||||
Logger(name string, options ...LoggerOption) Logger
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// attributesInlineCount is the number of attributes that are efficiently
|
||||
// stored in an array within a Record. This value is borrowed from slog, which
|
||||
// performed a quantitative survey of log library use and found that this value
|
||||
// covers 95% of all use cases (https://go.dev/blog/slog#performance).
|
||||
const attributesInlineCount = 5
|
||||
|
||||
// Record represents a log record.
|
||||
// A log record with a non-empty event name is interpreted as an event record.
|
||||
type Record struct {
|
||||
// Ensure forward compatibility by explicitly making this not comparable.
|
||||
noCmp [0]func() //nolint: unused // This is indeed used.
|
||||
|
||||
eventName string
|
||||
timestamp time.Time
|
||||
observedTimestamp time.Time
|
||||
severity Severity
|
||||
severityText string
|
||||
body attribute.Value
|
||||
err error
|
||||
|
||||
// The fields below are for optimizing the implementation of Attributes and
|
||||
// AddAttributes. This design is borrowed from the slog Record type:
|
||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.22.0:src/log/slog/record.go;l=20
|
||||
|
||||
// Allocation optimization: an inline array sized to hold
|
||||
// the majority of log calls (based on examination of open-source
|
||||
// code). It holds the start of the list of attributes.
|
||||
front [attributesInlineCount]attribute.KeyValue
|
||||
|
||||
// The number of attributes in front.
|
||||
nFront int
|
||||
|
||||
// The list of attributes except for those in front.
|
||||
// Invariants:
|
||||
// - len(back) > 0 if nFront == len(front)
|
||||
// - Unused array elements are zeroed to detect mistakes.
|
||||
back []attribute.KeyValue
|
||||
}
|
||||
|
||||
// EventName returns the event name.
|
||||
// A log record with a non-empty event name is interpreted as an event record.
|
||||
func (r *Record) EventName() string {
|
||||
return r.eventName
|
||||
}
|
||||
|
||||
// SetEventName sets the event name.
|
||||
// A log record with a non-empty event name is interpreted as an event record.
|
||||
// Event names should uniquely identify the structure of the event's attributes
|
||||
// and body.
|
||||
func (r *Record) SetEventName(s string) {
|
||||
r.eventName = s
|
||||
}
|
||||
|
||||
// Timestamp returns the time when the log record occurred.
|
||||
func (r *Record) Timestamp() time.Time {
|
||||
return r.timestamp
|
||||
}
|
||||
|
||||
// SetTimestamp sets the time when the log record occurred.
|
||||
func (r *Record) SetTimestamp(t time.Time) {
|
||||
r.timestamp = t
|
||||
}
|
||||
|
||||
// ObservedTimestamp returns the time when the log record was observed.
|
||||
func (r *Record) ObservedTimestamp() time.Time {
|
||||
return r.observedTimestamp
|
||||
}
|
||||
|
||||
// SetObservedTimestamp sets the time when the log record was observed.
|
||||
func (r *Record) SetObservedTimestamp(t time.Time) {
|
||||
r.observedTimestamp = t
|
||||
}
|
||||
|
||||
// Severity returns the [Severity] of the log record.
|
||||
func (r *Record) Severity() Severity {
|
||||
return r.severity
|
||||
}
|
||||
|
||||
// SetSeverity sets the [Severity] level of the log record.
|
||||
func (r *Record) SetSeverity(level Severity) {
|
||||
r.severity = level
|
||||
}
|
||||
|
||||
// SeverityText returns the text of the severity (also known as the log level)
|
||||
// as originally known at the source.
|
||||
func (r *Record) SeverityText() string {
|
||||
return r.severityText
|
||||
}
|
||||
|
||||
// SetSeverityText sets the text of the severity (also known as the log level)
|
||||
// as originally known at the source.
|
||||
func (r *Record) SetSeverityText(text string) {
|
||||
r.severityText = text
|
||||
}
|
||||
|
||||
// Body returns the body of the log record.
|
||||
func (r *Record) Body() attribute.Value {
|
||||
return r.body
|
||||
}
|
||||
|
||||
// SetBody sets the body of the log record.
|
||||
func (r *Record) SetBody(v attribute.Value) {
|
||||
r.body = v
|
||||
}
|
||||
|
||||
// Err returns the associated error if one has been set.
|
||||
func (r *Record) Err() error {
|
||||
return r.err
|
||||
}
|
||||
|
||||
// SetErr sets the associated error. Passing nil clears the error.
|
||||
func (r *Record) SetErr(err error) {
|
||||
r.err = err
|
||||
}
|
||||
|
||||
// WalkAttributes walks all attributes in the log record by calling f for each
|
||||
// [attribute.KeyValue] in the [Record]. Iteration stops if f returns false.
|
||||
func (r *Record) WalkAttributes(f func(attribute.KeyValue) bool) {
|
||||
for i := 0; i < r.nFront; i++ {
|
||||
if !f(r.front[i]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, a := range r.back {
|
||||
if !f(a) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddAttributes adds attributes to the log record.
|
||||
func (r *Record) AddAttributes(attrs ...attribute.KeyValue) {
|
||||
var i int
|
||||
for i = 0; i < len(attrs) && r.nFront < len(r.front); i++ {
|
||||
a := attrs[i]
|
||||
r.front[r.nFront] = a
|
||||
r.nFront++
|
||||
}
|
||||
|
||||
r.back = slices.Grow(r.back, len(attrs[i:]))
|
||||
r.back = append(r.back, attrs[i:]...)
|
||||
}
|
||||
|
||||
// AttributesLen returns the number of attributes in the log record.
|
||||
func (r *Record) AttributesLen() int {
|
||||
return r.nFront + len(r.back)
|
||||
}
|
||||
|
||||
// Clone returns a copy of the record with no shared state.
|
||||
// The original record and the clone can both be modified without interfering
|
||||
// with each other.
|
||||
func (r *Record) Clone() Record {
|
||||
res := *r
|
||||
res.back = slices.Clone(r.back)
|
||||
return res
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//go:generate stringer -type=Severity -linecomment
|
||||
|
||||
package log
|
||||
|
||||
// Severity represents a log record's severity (also known as its log level).
|
||||
// Smaller numerical values correspond to less severe log records (such as
|
||||
// debug events); larger numerical values correspond to more severe log records
|
||||
// (such as errors and critical events).
|
||||
type Severity int
|
||||
|
||||
// The following Severity values are defined by OpenTelemetry.
|
||||
const (
|
||||
// SeverityUndefined represents an unset Severity.
|
||||
SeverityUndefined Severity = 0 // UNDEFINED
|
||||
|
||||
// The following are severity values for fine-grained debugging log records.
|
||||
// They are typically disabled in default configurations.
|
||||
SeverityTrace1 Severity = 1 // TRACE
|
||||
SeverityTrace2 Severity = 2 // TRACE2
|
||||
SeverityTrace3 Severity = 3 // TRACE3
|
||||
SeverityTrace4 Severity = 4 // TRACE4
|
||||
|
||||
// The following are severity values for debugging log records.
|
||||
SeverityDebug1 Severity = 5 // DEBUG
|
||||
SeverityDebug2 Severity = 6 // DEBUG2
|
||||
SeverityDebug3 Severity = 7 // DEBUG3
|
||||
SeverityDebug4 Severity = 8 // DEBUG4
|
||||
|
||||
// The following are severity values for informational log records indicating
|
||||
// that an event happened.
|
||||
SeverityInfo1 Severity = 9 // INFO
|
||||
SeverityInfo2 Severity = 10 // INFO2
|
||||
SeverityInfo3 Severity = 11 // INFO3
|
||||
SeverityInfo4 Severity = 12 // INFO4
|
||||
|
||||
// The following are severity values for warning log records. These records
|
||||
// are not errors, but they are likely more important than informational
|
||||
// events.
|
||||
SeverityWarn1 Severity = 13 // WARN
|
||||
SeverityWarn2 Severity = 14 // WARN2
|
||||
SeverityWarn3 Severity = 15 // WARN3
|
||||
SeverityWarn4 Severity = 16 // WARN4
|
||||
|
||||
// The following are severity values for error log records indicating that
|
||||
// something went wrong.
|
||||
SeverityError1 Severity = 17 // ERROR
|
||||
SeverityError2 Severity = 18 // ERROR2
|
||||
SeverityError3 Severity = 19 // ERROR3
|
||||
SeverityError4 Severity = 20 // ERROR4
|
||||
|
||||
// The following are severity values for fatal log records, such as those
|
||||
// associated with an application or system crash.
|
||||
SeverityFatal1 Severity = 21 // FATAL
|
||||
SeverityFatal2 Severity = 22 // FATAL2
|
||||
SeverityFatal3 Severity = 23 // FATAL3
|
||||
SeverityFatal4 Severity = 24 // FATAL4
|
||||
|
||||
// The following are convenience definitions for the base severity of each
|
||||
// level.
|
||||
SeverityTrace = SeverityTrace1
|
||||
SeverityDebug = SeverityDebug1
|
||||
SeverityInfo = SeverityInfo1
|
||||
SeverityWarn = SeverityWarn1
|
||||
SeverityError = SeverityError1
|
||||
SeverityFatal = SeverityFatal1
|
||||
)
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// Code generated by "stringer -type=Severity -linecomment"; DO NOT EDIT.
|
||||
|
||||
package log
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[SeverityUndefined-0]
|
||||
_ = x[SeverityTrace1-1]
|
||||
_ = x[SeverityTrace2-2]
|
||||
_ = x[SeverityTrace3-3]
|
||||
_ = x[SeverityTrace4-4]
|
||||
_ = x[SeverityDebug1-5]
|
||||
_ = x[SeverityDebug2-6]
|
||||
_ = x[SeverityDebug3-7]
|
||||
_ = x[SeverityDebug4-8]
|
||||
_ = x[SeverityInfo1-9]
|
||||
_ = x[SeverityInfo2-10]
|
||||
_ = x[SeverityInfo3-11]
|
||||
_ = x[SeverityInfo4-12]
|
||||
_ = x[SeverityWarn1-13]
|
||||
_ = x[SeverityWarn2-14]
|
||||
_ = x[SeverityWarn3-15]
|
||||
_ = x[SeverityWarn4-16]
|
||||
_ = x[SeverityError1-17]
|
||||
_ = x[SeverityError2-18]
|
||||
_ = x[SeverityError3-19]
|
||||
_ = x[SeverityError4-20]
|
||||
_ = x[SeverityFatal1-21]
|
||||
_ = x[SeverityFatal2-22]
|
||||
_ = x[SeverityFatal3-23]
|
||||
_ = x[SeverityFatal4-24]
|
||||
}
|
||||
|
||||
const _Severity_name = "UNDEFINEDTRACETRACE2TRACE3TRACE4DEBUGDEBUG2DEBUG3DEBUG4INFOINFO2INFO3INFO4WARNWARN2WARN3WARN4ERRORERROR2ERROR3ERROR4FATALFATAL2FATAL3FATAL4"
|
||||
|
||||
var _Severity_index = [...]uint8{0, 9, 14, 20, 26, 32, 37, 43, 49, 55, 59, 64, 69, 74, 78, 83, 88, 93, 98, 104, 110, 116, 121, 127, 133, 139}
|
||||
|
||||
func (i Severity) String() string {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_Severity_index)-1 {
|
||||
return "Severity(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Severity_name[_Severity_index[idx]:_Severity_index[idx+1]]
|
||||
}
|
||||
+1
-1
@@ -320,7 +320,7 @@ type Observer interface {
|
||||
ObserveInt64(obsrv Int64Observable, value int64, opts ...ObserveOption)
|
||||
}
|
||||
|
||||
// Registration is an token representing the unique registration of a callback
|
||||
// Registration is a token representing the unique registration of a callback
|
||||
// for a set of instruments with a Meter.
|
||||
//
|
||||
// Warning: Methods may be added to this interface in minor releases. See
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package hextable provides a lookup table for decoding lowercase
|
||||
// hexadecimal.
|
||||
package hextable
|
||||
|
||||
// Rev is a reverse hex lookup table for lowercase hex digits. Valid
|
||||
// hexadecimal characters are indexed at their respective values. All other
|
||||
// characters, including the upper-case A-F disallowed by the W3C trace
|
||||
// context specification, are represented with '\xff'.
|
||||
//
|
||||
// The '\xff' character is used as invalid because no valid character has the
|
||||
// upper 4 bits set. Meaning, an efficient validation can be performed over
|
||||
// multiple character parsing by checking these bits remain zero.
|
||||
const Rev = "" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
+12
-15
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/propagation/internal/hextable"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
@@ -126,27 +127,23 @@ func (TraceContext) extract(carrier TextMapCarrier) trace.SpanContext {
|
||||
return sc
|
||||
}
|
||||
|
||||
// upperHex detect hex is upper case Unicode characters.
|
||||
func upperHex(v string) bool {
|
||||
for _, c := range v {
|
||||
if c >= 'A' && c <= 'F' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func extractPart(dst []byte, h *string, n int) bool {
|
||||
part, left, _ := strings.Cut(*h, delimiter)
|
||||
*h = left
|
||||
// hex.Decode decodes unsupported upper-case characters, so exclude explicitly.
|
||||
if len(part) != n || upperHex(part) {
|
||||
if len(part) != n {
|
||||
return false
|
||||
}
|
||||
if p, err := hex.Decode(dst, []byte(part)); err != nil || p != n/2 {
|
||||
return false
|
||||
// hextable.Rev maps every invalid character to 0xff, including the
|
||||
// upper-case A-F the specification disallows. OR-ing every looked-up value
|
||||
// together lets a single check detect any invalid character, because no
|
||||
// valid value has the upper 4 bits set.
|
||||
invalidMark := byte(0)
|
||||
for i := 0; i < n; i += 2 {
|
||||
hi, lo := hextable.Rev[part[i]], hextable.Rev[part[i+1]]
|
||||
dst[i/2] = (hi << 4) | lo
|
||||
invalidMark |= hi | lo
|
||||
}
|
||||
return true
|
||||
return invalidMark&0xf0 == 0
|
||||
}
|
||||
|
||||
// Fields returns the keys who's values are set with Inject.
|
||||
|
||||
+524
-22
@@ -28,40 +28,142 @@ type rawValue struct {
|
||||
slice any
|
||||
}
|
||||
|
||||
// Value returns value with all map values deduplicated and whether it changed.
|
||||
type valueChanges uint8
|
||||
|
||||
const (
|
||||
depthLimitChanged valueChanges = 1 << iota
|
||||
deduplicationChanged
|
||||
)
|
||||
|
||||
// ValueDedup returns value with all map values deduplicated and whether
|
||||
// it changed.
|
||||
//
|
||||
// Duplicate map keys are resolved using last-value-wins semantics.
|
||||
func Value(value attribute.Value) (attribute.Value, bool) {
|
||||
func ValueDedup(value attribute.Value) (attribute.Value, bool) {
|
||||
switch value.Type() {
|
||||
case attribute.SLICE:
|
||||
return deduplicateSliceValue(value)
|
||||
return sliceValueDedup(value)
|
||||
case attribute.MAP:
|
||||
return deduplicateMapValue(value)
|
||||
return mapValueDedup(value)
|
||||
default:
|
||||
return value, false
|
||||
}
|
||||
}
|
||||
|
||||
// KeyValue returns kv with all map values deduplicated and whether it changed.
|
||||
func KeyValue(kv attribute.KeyValue) (attribute.KeyValue, bool) {
|
||||
value, changed := Value(kv.Value)
|
||||
// ValueDedupLimitDepth returns value with all map values
|
||||
// deduplicated and all array and map values limited to depthLimit. The boolean
|
||||
// results report depth limiting and deduplication changes, respectively.
|
||||
//
|
||||
// Duplicate map keys are resolved using last-value-wins semantics. Depth
|
||||
// starts at one for value and increments when descending into an array element
|
||||
// or map value. An array or map beyond a non-negative depthLimit is replaced by
|
||||
// an empty value. A negative depthLimit disables depth limiting.
|
||||
func ValueDedupLimitDepth(
|
||||
value attribute.Value,
|
||||
depthLimit int,
|
||||
) (attribute.Value, bool, bool) {
|
||||
if depthLimit < 0 {
|
||||
value, deduplicated := ValueDedup(value)
|
||||
return value, false, deduplicated
|
||||
}
|
||||
|
||||
// Keep the common scalar and primitive-array cases in this wrapper. Routing
|
||||
// them through the recursive, multi-result transform adds measurable
|
||||
// overhead to the dominant simple attribute path.
|
||||
switch value.Type() {
|
||||
case attribute.BOOLSLICE,
|
||||
attribute.INT64SLICE,
|
||||
attribute.FLOAT64SLICE,
|
||||
attribute.STRINGSLICE,
|
||||
attribute.BYTESLICE:
|
||||
if depthLimit == 0 {
|
||||
return attribute.Value{}, true, false
|
||||
}
|
||||
return value, false, false
|
||||
case attribute.SLICE, attribute.MAP:
|
||||
default:
|
||||
return value, false, false
|
||||
}
|
||||
|
||||
value, changes := valueDedupLimitDepth(value, depthLimit)
|
||||
return value, changes&depthLimitChanged != 0, changes&deduplicationChanged != 0
|
||||
}
|
||||
|
||||
// ValueLimitDepth returns value with all array and map values limited to
|
||||
// depthLimit. Map keys are not deduplicated.
|
||||
//
|
||||
// Depth starts at one for value and increments when descending into an array
|
||||
// element or map value. An array or map beyond a non-negative depthLimit is
|
||||
// replaced by an empty value. A negative depthLimit disables depth limiting.
|
||||
func ValueLimitDepth(value attribute.Value, depthLimit int) (attribute.Value, bool) {
|
||||
if depthLimit < 0 {
|
||||
return value, false
|
||||
}
|
||||
|
||||
switch value.Type() {
|
||||
case attribute.BOOLSLICE,
|
||||
attribute.INT64SLICE,
|
||||
attribute.FLOAT64SLICE,
|
||||
attribute.STRINGSLICE,
|
||||
attribute.BYTESLICE:
|
||||
if depthLimit == 0 {
|
||||
return attribute.Value{}, true
|
||||
}
|
||||
return value, false
|
||||
case attribute.SLICE, attribute.MAP:
|
||||
default:
|
||||
return value, false
|
||||
}
|
||||
|
||||
return valueLimitDepth(value, depthLimit)
|
||||
}
|
||||
|
||||
// KeyValueDedup returns kv with all map values deduplicated and whether
|
||||
// it changed.
|
||||
func KeyValueDedup(kv attribute.KeyValue) (attribute.KeyValue, bool) {
|
||||
value, changed := ValueDedup(kv.Value)
|
||||
if changed {
|
||||
kv.Value = value
|
||||
}
|
||||
return kv, changed
|
||||
}
|
||||
|
||||
// KeyValues returns kvs with all map values deduplicated and whether they changed.
|
||||
// KeyValueDedupLimitDepth returns kv with all map values
|
||||
// deduplicated and all array and map values limited to depthLimit. The boolean
|
||||
// results report depth limiting and deduplication changes, respectively.
|
||||
func KeyValueDedupLimitDepth(
|
||||
kv attribute.KeyValue,
|
||||
depthLimit int,
|
||||
) (attribute.KeyValue, bool, bool) {
|
||||
value, depthLimited, deduplicated := ValueDedupLimitDepth(kv.Value, depthLimit)
|
||||
if depthLimited || deduplicated {
|
||||
kv.Value = value
|
||||
}
|
||||
return kv, depthLimited, deduplicated
|
||||
}
|
||||
|
||||
// KeyValueLimitDepth returns kv with all array and map values limited to
|
||||
// depthLimit. Map keys are not deduplicated.
|
||||
func KeyValueLimitDepth(kv attribute.KeyValue, depthLimit int) (attribute.KeyValue, bool) {
|
||||
value, changed := ValueLimitDepth(kv.Value, depthLimit)
|
||||
if changed {
|
||||
kv.Value = value
|
||||
}
|
||||
return kv, changed
|
||||
}
|
||||
|
||||
// KeyValuesDedup returns kvs with all map values deduplicated and whether
|
||||
// they changed.
|
||||
//
|
||||
// The returned slice is the original kvs slice if no value needs
|
||||
// deduplication. Top-level keys in kvs are not deduplicated.
|
||||
func KeyValues(kvs []attribute.KeyValue) ([]attribute.KeyValue, bool) {
|
||||
func KeyValuesDedup(kvs []attribute.KeyValue) ([]attribute.KeyValue, bool) {
|
||||
// Preserve the caller's slice on the common no-op path. Once a changed
|
||||
// value is found, copy the prior values exactly once and fill the rest in
|
||||
// place as the scan continues.
|
||||
var normalized []attribute.KeyValue
|
||||
for i, kv := range kvs {
|
||||
kv, changed := KeyValue(kv)
|
||||
kv, changed := KeyValueDedup(kv)
|
||||
if normalized != nil {
|
||||
normalized[i] = kv
|
||||
continue
|
||||
@@ -80,22 +182,67 @@ func KeyValues(kvs []attribute.KeyValue) ([]attribute.KeyValue, bool) {
|
||||
return normalized, true
|
||||
}
|
||||
|
||||
// Set returns set with all map values deduplicated and whether it changed.
|
||||
// KeyValuesDedupLimitDepth returns kvs with all map values
|
||||
// deduplicated and all array and map values limited to depthLimit. The boolean
|
||||
// results report depth limiting and deduplication changes, respectively.
|
||||
//
|
||||
// The returned slice is the original kvs slice if no value needs
|
||||
// normalization. Top-level keys in kvs are not deduplicated.
|
||||
func KeyValuesDedupLimitDepth(
|
||||
kvs []attribute.KeyValue,
|
||||
depthLimit int,
|
||||
) ([]attribute.KeyValue, bool, bool) {
|
||||
if depthLimit < 0 {
|
||||
kvs, deduplicated := KeyValuesDedup(kvs)
|
||||
return kvs, false, deduplicated
|
||||
}
|
||||
|
||||
var normalized []attribute.KeyValue
|
||||
var allChanges valueChanges
|
||||
for i, kv := range kvs {
|
||||
value, changes := valueDedupLimitDepth(kv.Value, depthLimit)
|
||||
allChanges |= changes
|
||||
if changes != 0 {
|
||||
kv.Value = value
|
||||
}
|
||||
if normalized != nil {
|
||||
normalized[i] = kv
|
||||
continue
|
||||
}
|
||||
if changes == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.KeyValue, len(kvs))
|
||||
copy(normalized, kvs[:i])
|
||||
normalized[i] = kv
|
||||
}
|
||||
if normalized == nil {
|
||||
return kvs, false, false
|
||||
}
|
||||
return normalized,
|
||||
allChanges&depthLimitChanged != 0,
|
||||
allChanges&deduplicationChanged != 0
|
||||
}
|
||||
|
||||
// SetDedup returns set with all map values deduplicated and whether it
|
||||
// changed.
|
||||
//
|
||||
// The returned Set is the original set if no value needs deduplication.
|
||||
// Top-level key uniqueness remains attribute.Set's responsibility; this only
|
||||
// normalizes map attribute values.
|
||||
func Set(set attribute.Set) (attribute.Set, bool) {
|
||||
if set.Len() == 0 {
|
||||
func SetDedup(set attribute.Set) (attribute.Set, bool) {
|
||||
length := set.Len()
|
||||
if length == 0 {
|
||||
return set, false
|
||||
}
|
||||
|
||||
// Most attribute sets contain no duplicate map keys. Delay allocation until
|
||||
// the first changed value so the no-op path returns the original Set.
|
||||
var normalized []attribute.KeyValue
|
||||
for i := range set.Len() {
|
||||
for i := range length {
|
||||
kv, _ := set.Get(i)
|
||||
kv, changed := KeyValue(kv)
|
||||
kv, changed := KeyValueDedup(kv)
|
||||
if normalized != nil {
|
||||
normalized = append(normalized, kv)
|
||||
continue
|
||||
@@ -104,7 +251,7 @@ func Set(set attribute.Set) (attribute.Set, bool) {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.KeyValue, 0, set.Len())
|
||||
normalized = make([]attribute.KeyValue, 0, length)
|
||||
for j := range i {
|
||||
prior, _ := set.Get(j)
|
||||
normalized = append(normalized, prior)
|
||||
@@ -118,7 +265,359 @@ func Set(set attribute.Set) (attribute.Set, bool) {
|
||||
return attribute.NewSet(normalized...), true
|
||||
}
|
||||
|
||||
func deduplicateSliceValue(value attribute.Value) (attribute.Value, bool) {
|
||||
// SetDedupLimitDepth returns set with all map values deduplicated and
|
||||
// all array and map values limited to depthLimit. The boolean results report
|
||||
// depth limiting and deduplication changes, respectively.
|
||||
//
|
||||
// The returned Set is the original set if no value needs normalization.
|
||||
// Top-level key uniqueness remains attribute.Set's responsibility; this only
|
||||
// normalizes attribute values.
|
||||
func SetDedupLimitDepth(
|
||||
set attribute.Set,
|
||||
depthLimit int,
|
||||
) (attribute.Set, bool, bool) {
|
||||
if depthLimit < 0 {
|
||||
set, deduplicated := SetDedup(set)
|
||||
return set, false, deduplicated
|
||||
}
|
||||
length := set.Len()
|
||||
if length == 0 {
|
||||
return set, false, false
|
||||
}
|
||||
|
||||
var normalized []attribute.KeyValue
|
||||
var allChanges valueChanges
|
||||
for i := range length {
|
||||
kv, _ := set.Get(i)
|
||||
value, changes := valueDedupLimitDepth(kv.Value, depthLimit)
|
||||
allChanges |= changes
|
||||
if changes != 0 {
|
||||
kv.Value = value
|
||||
}
|
||||
if normalized != nil {
|
||||
normalized = append(normalized, kv)
|
||||
continue
|
||||
}
|
||||
if changes == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.KeyValue, 0, length)
|
||||
for j := range i {
|
||||
prior, _ := set.Get(j)
|
||||
normalized = append(normalized, prior)
|
||||
}
|
||||
normalized = append(normalized, kv)
|
||||
}
|
||||
if normalized == nil {
|
||||
return set, false, false
|
||||
}
|
||||
return attribute.NewSet(normalized...),
|
||||
allChanges&depthLimitChanged != 0,
|
||||
allChanges&deduplicationChanged != 0
|
||||
}
|
||||
|
||||
// SetLimitDepth returns set with all array and map values limited to
|
||||
// depthLimit. Map keys are not deduplicated.
|
||||
//
|
||||
// The returned Set is the original set if no value changes.
|
||||
func SetLimitDepth(set attribute.Set, depthLimit int) (attribute.Set, bool) {
|
||||
if depthLimit < 0 {
|
||||
return set, false
|
||||
}
|
||||
length := set.Len()
|
||||
if length == 0 {
|
||||
return set, false
|
||||
}
|
||||
|
||||
var normalized []attribute.KeyValue
|
||||
for i := range length {
|
||||
kv, _ := set.Get(i)
|
||||
value, changed := valueLimitDepth(kv.Value, depthLimit)
|
||||
if changed {
|
||||
kv.Value = value
|
||||
}
|
||||
if normalized != nil {
|
||||
normalized = append(normalized, kv)
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.KeyValue, 0, length)
|
||||
for j := range i {
|
||||
prior, _ := set.Get(j)
|
||||
normalized = append(normalized, prior)
|
||||
}
|
||||
normalized = append(normalized, kv)
|
||||
}
|
||||
if normalized == nil {
|
||||
return set, false
|
||||
}
|
||||
return attribute.NewSet(normalized...), true
|
||||
}
|
||||
|
||||
// valueDedupLimitDepth combines depth limiting with recursive map
|
||||
// deduplication. remainingDepth is non-negative. It checks the remaining
|
||||
// budget before reading collection storage and lazily rebuilds only changed
|
||||
// ancestry.
|
||||
func valueDedupLimitDepth(
|
||||
value attribute.Value,
|
||||
remainingDepth int,
|
||||
) (attribute.Value, valueChanges) {
|
||||
switch value.Type() {
|
||||
case attribute.BOOLSLICE,
|
||||
attribute.INT64SLICE,
|
||||
attribute.FLOAT64SLICE,
|
||||
attribute.STRINGSLICE,
|
||||
attribute.BYTESLICE:
|
||||
if remainingDepth == 0 {
|
||||
return attribute.Value{}, depthLimitChanged
|
||||
}
|
||||
case attribute.SLICE:
|
||||
if remainingDepth == 0 {
|
||||
return attribute.Value{}, depthLimitChanged
|
||||
}
|
||||
return sliceValueDedupLimitDepth(value, remainingDepth)
|
||||
case attribute.MAP:
|
||||
if remainingDepth == 0 {
|
||||
return attribute.Value{}, depthLimitChanged
|
||||
}
|
||||
return mapValueDedupLimitDepth(value, remainingDepth)
|
||||
}
|
||||
return value, 0
|
||||
}
|
||||
|
||||
// valueLimitDepth limits collection depth while preserving duplicate map keys.
|
||||
func valueLimitDepth(
|
||||
value attribute.Value,
|
||||
remainingDepth int,
|
||||
) (attribute.Value, bool) {
|
||||
switch value.Type() {
|
||||
case attribute.BOOLSLICE,
|
||||
attribute.INT64SLICE,
|
||||
attribute.FLOAT64SLICE,
|
||||
attribute.STRINGSLICE,
|
||||
attribute.BYTESLICE:
|
||||
if remainingDepth == 0 {
|
||||
return attribute.Value{}, true
|
||||
}
|
||||
case attribute.SLICE:
|
||||
if remainingDepth == 0 {
|
||||
return attribute.Value{}, true
|
||||
}
|
||||
return sliceValueLimitDepth(value, remainingDepth)
|
||||
case attribute.MAP:
|
||||
if remainingDepth == 0 {
|
||||
return attribute.Value{}, true
|
||||
}
|
||||
return mapValueLimitDepth(value, remainingDepth)
|
||||
}
|
||||
return value, false
|
||||
}
|
||||
|
||||
func sliceValueDedupLimitDepth(
|
||||
value attribute.Value,
|
||||
remainingDepth int,
|
||||
) (attribute.Value, valueChanges) {
|
||||
storage := valueStorage(value)
|
||||
length := valueLen(storage)
|
||||
if length <= 1 {
|
||||
if length == 1 {
|
||||
elem := valueAt(storage, 0)
|
||||
newElem, changes := valueDedupLimitDepth(
|
||||
elem,
|
||||
remainingDepth-1,
|
||||
)
|
||||
if changes != 0 {
|
||||
return attribute.SliceValue(newElem), changes
|
||||
}
|
||||
}
|
||||
return value, 0
|
||||
}
|
||||
|
||||
var normalized []attribute.Value
|
||||
var allChanges valueChanges
|
||||
for i := range length {
|
||||
elem := valueAt(storage, i)
|
||||
newElem, changes := valueDedupLimitDepth(
|
||||
elem,
|
||||
remainingDepth-1,
|
||||
)
|
||||
allChanges |= changes
|
||||
if normalized != nil {
|
||||
normalized[i] = newElem
|
||||
continue
|
||||
}
|
||||
if changes == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.Value, length)
|
||||
for j := range i {
|
||||
normalized[j] = valueAt(storage, j)
|
||||
}
|
||||
normalized[i] = newElem
|
||||
}
|
||||
if normalized == nil {
|
||||
return value, 0
|
||||
}
|
||||
return attribute.SliceValue(normalized...), allChanges
|
||||
}
|
||||
|
||||
func sliceValueLimitDepth(
|
||||
value attribute.Value,
|
||||
remainingDepth int,
|
||||
) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
length := valueLen(storage)
|
||||
if length <= 1 {
|
||||
if length == 1 {
|
||||
elem := valueAt(storage, 0)
|
||||
newElem, changed := valueLimitDepth(elem, remainingDepth-1)
|
||||
if changed {
|
||||
return attribute.SliceValue(newElem), true
|
||||
}
|
||||
}
|
||||
return value, false
|
||||
}
|
||||
|
||||
var normalized []attribute.Value
|
||||
for i := range length {
|
||||
elem := valueAt(storage, i)
|
||||
newElem, changed := valueLimitDepth(elem, remainingDepth-1)
|
||||
if normalized != nil {
|
||||
normalized[i] = newElem
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.Value, length)
|
||||
for j := range i {
|
||||
normalized[j] = valueAt(storage, j)
|
||||
}
|
||||
normalized[i] = newElem
|
||||
}
|
||||
if normalized == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.SliceValue(normalized...), true
|
||||
}
|
||||
|
||||
func mapValueDedupLimitDepth(
|
||||
value attribute.Value,
|
||||
remainingDepth int,
|
||||
) (attribute.Value, valueChanges) {
|
||||
storage := valueStorage(value)
|
||||
length := keyValueLen(storage)
|
||||
if length <= 1 {
|
||||
if length == 1 {
|
||||
kv := keyValueAt(storage, 0)
|
||||
newValue, changes := valueDedupLimitDepth(
|
||||
kv.Value,
|
||||
remainingDepth-1,
|
||||
)
|
||||
if changes != 0 {
|
||||
kv.Value = newValue
|
||||
return attribute.MapValue(kv), changes
|
||||
}
|
||||
}
|
||||
return value, 0
|
||||
}
|
||||
|
||||
var normalized []attribute.KeyValue
|
||||
var allChanges valueChanges
|
||||
for i := 0; i < length; {
|
||||
// attribute.MapValue stores key-values sorted by key using a stable
|
||||
// sort. Only the last entry in an equal-key run survives, so avoid
|
||||
// traversing values that will be discarded.
|
||||
first := keyValueAt(storage, i)
|
||||
j := i + 1
|
||||
for j < length && keyValueAt(storage, j).Key == first.Key {
|
||||
j++
|
||||
}
|
||||
|
||||
kv := keyValueAt(storage, j-1)
|
||||
newValue, changes := valueDedupLimitDepth(
|
||||
kv.Value,
|
||||
remainingDepth-1,
|
||||
)
|
||||
if changes != 0 {
|
||||
kv.Value = newValue
|
||||
}
|
||||
if j-i > 1 {
|
||||
changes |= deduplicationChanged
|
||||
}
|
||||
allChanges |= changes
|
||||
if normalized != nil {
|
||||
normalized = append(normalized, kv)
|
||||
} else if changes != 0 {
|
||||
if i == 0 && j == length {
|
||||
return attribute.MapValue(kv), allChanges
|
||||
}
|
||||
normalized = make([]attribute.KeyValue, 0, length-(j-i-1))
|
||||
for k := range i {
|
||||
normalized = append(normalized, keyValueAt(storage, k))
|
||||
}
|
||||
normalized = append(normalized, kv)
|
||||
}
|
||||
i = j
|
||||
}
|
||||
if normalized == nil {
|
||||
return value, 0
|
||||
}
|
||||
return attribute.MapValue(normalized...), allChanges
|
||||
}
|
||||
|
||||
func mapValueLimitDepth(
|
||||
value attribute.Value,
|
||||
remainingDepth int,
|
||||
) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
length := keyValueLen(storage)
|
||||
if length <= 1 {
|
||||
if length == 1 {
|
||||
kv := keyValueAt(storage, 0)
|
||||
newValue, changed := valueLimitDepth(kv.Value, remainingDepth-1)
|
||||
if changed {
|
||||
kv.Value = newValue
|
||||
return attribute.MapValue(kv), true
|
||||
}
|
||||
}
|
||||
return value, false
|
||||
}
|
||||
|
||||
var normalized []attribute.KeyValue
|
||||
for i := range length {
|
||||
kv := keyValueAt(storage, i)
|
||||
newValue, changed := valueLimitDepth(kv.Value, remainingDepth-1)
|
||||
if changed {
|
||||
kv.Value = newValue
|
||||
}
|
||||
if normalized != nil {
|
||||
normalized[i] = kv
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
normalized = make([]attribute.KeyValue, length)
|
||||
for j := range i {
|
||||
normalized[j] = keyValueAt(storage, j)
|
||||
}
|
||||
normalized[i] = kv
|
||||
}
|
||||
if normalized == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.MapValue(normalized...), true
|
||||
}
|
||||
|
||||
func sliceValueDedup(value attribute.Value) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
length := valueLen(storage)
|
||||
|
||||
@@ -127,7 +626,7 @@ func deduplicateSliceValue(value attribute.Value) (attribute.Value, bool) {
|
||||
var normalized []attribute.Value
|
||||
for i := range length {
|
||||
elem := valueAt(storage, i)
|
||||
elem, changed := Value(elem)
|
||||
elem, changed := ValueDedup(elem)
|
||||
if normalized != nil {
|
||||
normalized[i] = elem
|
||||
continue
|
||||
@@ -148,14 +647,14 @@ func deduplicateSliceValue(value attribute.Value) (attribute.Value, bool) {
|
||||
return attribute.SliceValue(normalized...), true
|
||||
}
|
||||
|
||||
func deduplicateMapValue(value attribute.Value) (attribute.Value, bool) {
|
||||
func mapValueDedup(value attribute.Value) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
length := keyValueLen(storage)
|
||||
if length <= 1 {
|
||||
// A single map entry cannot duplicate its own key, but its value might
|
||||
// contain a map or slice that needs recursive normalization.
|
||||
if length == 1 {
|
||||
kv, changed := KeyValue(keyValueAt(storage, 0))
|
||||
kv, changed := KeyValueDedup(keyValueAt(storage, 0))
|
||||
if changed {
|
||||
return attribute.MapValue(kv), true
|
||||
}
|
||||
@@ -174,13 +673,16 @@ func deduplicateMapValue(value attribute.Value) (attribute.Value, bool) {
|
||||
j++
|
||||
}
|
||||
|
||||
kv, nestedChanged := KeyValue(keyValueAt(storage, j-1))
|
||||
kv, nestedChanged := KeyValueDedup(keyValueAt(storage, j-1))
|
||||
// j-i > 1 means the current key run contained duplicates.
|
||||
changed := nestedChanged || j-i > 1
|
||||
if normalized != nil {
|
||||
normalized = append(normalized, kv)
|
||||
} else if changed {
|
||||
normalized = make([]attribute.KeyValue, 0, length)
|
||||
if i == 0 && j == length {
|
||||
return attribute.MapValue(kv), true
|
||||
}
|
||||
normalized = make([]attribute.KeyValue, 0, length-(j-i-1))
|
||||
for k := range i {
|
||||
normalized = append(normalized, keyValueAt(storage, k))
|
||||
}
|
||||
|
||||
+277
-91
@@ -7,7 +7,7 @@
|
||||
package attrnorm
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -26,43 +26,24 @@ func Truncate(limit int, attr attribute.KeyValue) attribute.KeyValue {
|
||||
if limit < 0 {
|
||||
return attr
|
||||
}
|
||||
|
||||
// Keep scalar cases in this wrapper. Routing them through the recursive,
|
||||
// multi-result transform adds measurable overhead to the dominant simple
|
||||
// attribute path.
|
||||
switch attr.Value.Type() {
|
||||
case attribute.STRING:
|
||||
v := attr.Value.AsString()
|
||||
return attr.Key.String(truncate(limit, v))
|
||||
case attribute.STRINGSLICE:
|
||||
v := attr.Value.AsStringSlice()
|
||||
for i := range v {
|
||||
v[i] = truncate(limit, v[i])
|
||||
}
|
||||
return attr.Key.StringSlice(v)
|
||||
attr.Value = attribute.StringValue(truncate(limit, attr.Value.AsString()))
|
||||
case attribute.BYTESLICE:
|
||||
v := attr.Value.AsString()
|
||||
if len(v) > limit {
|
||||
return attr.Key.ByteSlice([]byte(v[:limit]))
|
||||
s := attr.Value.AsString()
|
||||
if len(s) > limit {
|
||||
attr.Value = attribute.ByteSliceValue([]byte(s[:limit]))
|
||||
}
|
||||
return attr
|
||||
case attribute.STRINGSLICE:
|
||||
attr.Value, _ = truncateStringSliceValue(limit, attr.Value)
|
||||
case attribute.SLICE:
|
||||
v := attr.Value.AsSlice()
|
||||
if !slices.ContainsFunc(v, func(e attribute.Value) bool { return needsTruncation(limit, e) }) {
|
||||
return attr
|
||||
}
|
||||
newV := make([]attribute.Value, len(v))
|
||||
for i, elem := range v {
|
||||
newV[i] = TruncateValue(limit, elem)
|
||||
}
|
||||
return attr.Key.Slice(newV...)
|
||||
attr.Value, _ = truncateSliceValue(limit, attr.Value)
|
||||
case attribute.MAP:
|
||||
v := attr.Value.AsMap()
|
||||
if !slices.ContainsFunc(v, func(kv attribute.KeyValue) bool { return needsTruncation(limit, kv.Value) }) {
|
||||
return attr
|
||||
}
|
||||
newV := make([]attribute.KeyValue, len(v))
|
||||
for i, elem := range v {
|
||||
elem.Value = TruncateValue(limit, elem.Value)
|
||||
newV[i] = elem
|
||||
}
|
||||
return attr.Key.Map(newV...)
|
||||
attr.Value, _ = truncateMapValue(limit, attr.Value)
|
||||
}
|
||||
return attr
|
||||
}
|
||||
@@ -76,85 +57,275 @@ func TruncateValue(limit int, v attribute.Value) attribute.Value {
|
||||
return v
|
||||
}
|
||||
|
||||
// Match Truncate's direct scalar path to avoid paying for the recursive,
|
||||
// multi-result transform when no composite traversal is needed.
|
||||
switch v.Type() {
|
||||
case attribute.STRING:
|
||||
return attribute.StringValue(truncate(limit, v.AsString()))
|
||||
case attribute.STRINGSLICE:
|
||||
ss := v.AsStringSlice()
|
||||
for i := range ss {
|
||||
ss[i] = truncate(limit, ss[i])
|
||||
}
|
||||
return attribute.StringSliceValue(ss)
|
||||
case attribute.BYTESLICE:
|
||||
// len(v.AsString()) is identical to len(v.AsByteSlice()) but
|
||||
// avoids allocating the full slice before truncation.
|
||||
s := v.AsString()
|
||||
if limit >= 0 && len(s) > limit {
|
||||
if len(s) > limit {
|
||||
return attribute.ByteSliceValue([]byte(s[:limit]))
|
||||
}
|
||||
case attribute.STRINGSLICE:
|
||||
v, _ = truncateStringSliceValue(limit, v)
|
||||
case attribute.SLICE:
|
||||
sl := v.AsSlice()
|
||||
if !slices.ContainsFunc(sl, func(e attribute.Value) bool { return needsTruncation(limit, e) }) {
|
||||
return v
|
||||
}
|
||||
newSl := make([]attribute.Value, len(sl))
|
||||
for i, elem := range sl {
|
||||
newSl[i] = TruncateValue(limit, elem)
|
||||
}
|
||||
return attribute.SliceValue(newSl...)
|
||||
v, _ = truncateSliceValue(limit, v)
|
||||
case attribute.MAP:
|
||||
m := v.AsMap()
|
||||
if !slices.ContainsFunc(m, func(kv attribute.KeyValue) bool { return needsTruncation(limit, kv.Value) }) {
|
||||
return v
|
||||
}
|
||||
newM := make([]attribute.KeyValue, len(m))
|
||||
for i, elem := range m {
|
||||
elem.Value = TruncateValue(limit, elem.Value)
|
||||
newM[i] = elem
|
||||
}
|
||||
return attribute.MapValue(newM...)
|
||||
v, _ = truncateMapValue(limit, v)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// stringNeedsTruncation reports whether s would be modified by truncate for the
|
||||
// given limit.
|
||||
func stringNeedsTruncation(limit int, s string) bool {
|
||||
if limit < 0 || len(s) <= limit {
|
||||
return false
|
||||
}
|
||||
return utf8.RuneCountInString(s) > limit || !utf8.ValidString(s)
|
||||
}
|
||||
|
||||
// needsTruncation reports whether v would be modified by TruncateValue for the
|
||||
// given limit.
|
||||
func needsTruncation(limit int, v attribute.Value) bool {
|
||||
// truncateValue traverses composite values once and rebuilds them lazily on
|
||||
// the first changed child. Recursion provides O(depth) temporary stack space
|
||||
// without forcing a heap allocation on the common no-op path.
|
||||
func truncateValue(limit int, v attribute.Value) (attribute.Value, bool) {
|
||||
switch v.Type() {
|
||||
case attribute.STRING:
|
||||
return stringNeedsTruncation(limit, v.AsString())
|
||||
case attribute.BYTESLICE:
|
||||
// len(v.AsString()) is identical to len(v.AsByteSlice()) but
|
||||
// avoids memory allocation.
|
||||
if limit >= 0 && len(v.AsString()) > limit {
|
||||
return true
|
||||
s := v.AsString()
|
||||
truncated := truncate(limit, s)
|
||||
if truncated != s {
|
||||
return attribute.StringValue(truncated), true
|
||||
}
|
||||
case attribute.STRINGSLICE:
|
||||
for _, s := range v.AsStringSlice() {
|
||||
if stringNeedsTruncation(limit, s) {
|
||||
return true
|
||||
}
|
||||
return truncateStringSliceValue(limit, v)
|
||||
case attribute.BYTESLICE:
|
||||
// len(v.AsString()) is identical to len(v.AsByteSlice()) but
|
||||
// avoids allocating the full slice before truncation.
|
||||
s := v.AsString()
|
||||
if len(s) > limit {
|
||||
return attribute.ByteSliceValue([]byte(s[:limit])), true
|
||||
}
|
||||
case attribute.SLICE:
|
||||
return slices.ContainsFunc(v.AsSlice(), func(e attribute.Value) bool { return needsTruncation(limit, e) })
|
||||
return truncateSliceValue(limit, v)
|
||||
case attribute.MAP:
|
||||
return slices.ContainsFunc(
|
||||
v.AsMap(),
|
||||
func(kv attribute.KeyValue) bool { return needsTruncation(limit, kv.Value) },
|
||||
)
|
||||
return truncateMapValue(limit, v)
|
||||
}
|
||||
return false
|
||||
return v, false
|
||||
}
|
||||
|
||||
func truncateStringSliceValue(limit int, value attribute.Value) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
switch values := storage.(type) {
|
||||
case [0]string:
|
||||
return value, false
|
||||
case [1]string:
|
||||
return truncateStrings(limit, value, values[:])
|
||||
case [2]string:
|
||||
return truncateStrings(limit, value, values[:])
|
||||
case [3]string:
|
||||
return truncateStrings(limit, value, values[:])
|
||||
default:
|
||||
array := reflect.ValueOf(storage)
|
||||
if array.Kind() != reflect.Array || array.Type().Elem() != stringType {
|
||||
return value, false
|
||||
}
|
||||
return truncateStringArray(limit, value, array)
|
||||
}
|
||||
}
|
||||
|
||||
func truncateStrings(limit int, value attribute.Value, values []string) (attribute.Value, bool) {
|
||||
var truncated []string
|
||||
for i, s := range values {
|
||||
newS := truncate(limit, s)
|
||||
if truncated != nil {
|
||||
truncated[i] = newS
|
||||
continue
|
||||
}
|
||||
if newS == s {
|
||||
continue
|
||||
}
|
||||
|
||||
truncated = make([]string, len(values))
|
||||
copy(truncated, values[:i])
|
||||
truncated[i] = newS
|
||||
}
|
||||
if truncated == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.StringSliceValue(truncated), true
|
||||
}
|
||||
|
||||
func truncateStringArray(limit int, value attribute.Value, values reflect.Value) (attribute.Value, bool) {
|
||||
var truncated []string
|
||||
for i := range values.Len() {
|
||||
s := values.Index(i).String()
|
||||
newS := truncate(limit, s)
|
||||
if truncated != nil {
|
||||
truncated[i] = newS
|
||||
continue
|
||||
}
|
||||
if newS == s {
|
||||
continue
|
||||
}
|
||||
|
||||
truncated = make([]string, values.Len())
|
||||
for j := range i {
|
||||
truncated[j] = values.Index(j).String()
|
||||
}
|
||||
truncated[i] = newS
|
||||
}
|
||||
if truncated == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.StringSliceValue(truncated), true
|
||||
}
|
||||
|
||||
func truncateSliceValue(limit int, value attribute.Value) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
switch values := storage.(type) {
|
||||
case [0]attribute.Value:
|
||||
return value, false
|
||||
case [1]attribute.Value:
|
||||
return truncateValueSlice(limit, value, values[:])
|
||||
case [2]attribute.Value:
|
||||
return truncateValueSlice(limit, value, values[:])
|
||||
case [3]attribute.Value:
|
||||
return truncateValueSlice(limit, value, values[:])
|
||||
case [4]attribute.Value:
|
||||
return truncateValueSlice(limit, value, values[:])
|
||||
case [5]attribute.Value:
|
||||
return truncateValueSlice(limit, value, values[:])
|
||||
default:
|
||||
array := reflect.ValueOf(storage)
|
||||
if array.Kind() != reflect.Array || array.Type().Elem() != valueType {
|
||||
return value, false
|
||||
}
|
||||
return truncateValueArray(limit, value, array)
|
||||
}
|
||||
}
|
||||
|
||||
func truncateValueSlice(limit int, value attribute.Value, values []attribute.Value) (attribute.Value, bool) {
|
||||
var truncated []attribute.Value
|
||||
for i, elem := range values {
|
||||
newElem, changed := truncateValue(limit, elem)
|
||||
if truncated != nil {
|
||||
truncated[i] = newElem
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
truncated = make([]attribute.Value, len(values))
|
||||
copy(truncated, values[:i])
|
||||
truncated[i] = newElem
|
||||
}
|
||||
if truncated == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.SliceValue(truncated...), true
|
||||
}
|
||||
|
||||
func truncateValueArray(limit int, value attribute.Value, values reflect.Value) (attribute.Value, bool) {
|
||||
var truncated []attribute.Value
|
||||
for i := range values.Len() {
|
||||
elem := values.Index(i).Interface().(attribute.Value)
|
||||
newElem, changed := truncateValue(limit, elem)
|
||||
if truncated != nil {
|
||||
truncated[i] = newElem
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
truncated = make([]attribute.Value, values.Len())
|
||||
for j := range i {
|
||||
truncated[j] = values.Index(j).Interface().(attribute.Value)
|
||||
}
|
||||
truncated[i] = newElem
|
||||
}
|
||||
if truncated == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.SliceValue(truncated...), true
|
||||
}
|
||||
|
||||
func truncateMapValue(limit int, value attribute.Value) (attribute.Value, bool) {
|
||||
storage := valueStorage(value)
|
||||
switch keyValues := storage.(type) {
|
||||
case [0]attribute.KeyValue:
|
||||
return value, false
|
||||
case [1]attribute.KeyValue:
|
||||
return truncateKeyValueSlice(limit, value, keyValues[:])
|
||||
case [2]attribute.KeyValue:
|
||||
return truncateKeyValueSlice(limit, value, keyValues[:])
|
||||
case [3]attribute.KeyValue:
|
||||
return truncateKeyValueSlice(limit, value, keyValues[:])
|
||||
case [4]attribute.KeyValue:
|
||||
return truncateKeyValueSlice(limit, value, keyValues[:])
|
||||
case [5]attribute.KeyValue:
|
||||
return truncateKeyValueSlice(limit, value, keyValues[:])
|
||||
default:
|
||||
array := reflect.ValueOf(storage)
|
||||
if array.Kind() != reflect.Array || array.Type().Elem() != keyValueType {
|
||||
return value, false
|
||||
}
|
||||
return truncateKeyValueArray(limit, value, array)
|
||||
}
|
||||
}
|
||||
|
||||
func truncateKeyValueSlice(
|
||||
limit int,
|
||||
value attribute.Value,
|
||||
keyValues []attribute.KeyValue,
|
||||
) (attribute.Value, bool) {
|
||||
var truncated []attribute.KeyValue
|
||||
for i, kv := range keyValues {
|
||||
newValue, changed := truncateValue(limit, kv.Value)
|
||||
if changed {
|
||||
kv.Value = newValue
|
||||
}
|
||||
if truncated != nil {
|
||||
truncated[i] = kv
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
truncated = make([]attribute.KeyValue, len(keyValues))
|
||||
copy(truncated, keyValues[:i])
|
||||
truncated[i] = kv
|
||||
}
|
||||
if truncated == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.MapValue(truncated...), true
|
||||
}
|
||||
|
||||
func truncateKeyValueArray(limit int, value attribute.Value, keyValues reflect.Value) (attribute.Value, bool) {
|
||||
var truncated []attribute.KeyValue
|
||||
for i := range keyValues.Len() {
|
||||
kv := keyValues.Index(i).Interface().(attribute.KeyValue)
|
||||
newValue, changed := truncateValue(limit, kv.Value)
|
||||
if changed {
|
||||
kv.Value = newValue
|
||||
}
|
||||
if truncated != nil {
|
||||
truncated[i] = kv
|
||||
continue
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
truncated = make([]attribute.KeyValue, keyValues.Len())
|
||||
for j := range i {
|
||||
truncated[j] = keyValues.Index(j).Interface().(attribute.KeyValue)
|
||||
}
|
||||
truncated[i] = kv
|
||||
}
|
||||
if truncated == nil {
|
||||
return value, false
|
||||
}
|
||||
return attribute.MapValue(truncated...), true
|
||||
}
|
||||
|
||||
var stringType = reflect.TypeFor[string]()
|
||||
|
||||
// truncate returns a version of s truncated according to limit.
|
||||
//
|
||||
// If limit is negative, it returns the original string.
|
||||
@@ -168,7 +339,7 @@ func truncate(limit int, s string) string {
|
||||
// This prioritizes performance in the following order based on the most
|
||||
// common expected use cases.
|
||||
//
|
||||
// - Values shorter than the default limit (128).
|
||||
// - Values whose byte length does not exceed the limit.
|
||||
// - Strings with valid encodings that exceed the limit.
|
||||
// - No limit.
|
||||
// - Strings with invalid encodings that exceed the limit.
|
||||
@@ -188,14 +359,27 @@ func truncate(limit int, s string) string {
|
||||
continue
|
||||
}
|
||||
|
||||
// A zero limit also truncates a leading invalid byte or U+FFFD.
|
||||
if limit == 0 {
|
||||
return ""
|
||||
}
|
||||
// Range reports RuneError for both an invalid byte and a valid U+FFFD.
|
||||
// Only a size-1 decoding indicates invalid UTF-8.
|
||||
_, size := utf8.DecodeRuneInString(s[i:])
|
||||
if size == 1 {
|
||||
// Invalid encoding.
|
||||
// Removing this byte makes len(s)-1 an upper bound for a rebuilt
|
||||
// result. Keep the valid prefix before rescanning s[i:].
|
||||
b.Grow(len(s) - 1)
|
||||
_, _ = b.WriteString(s[:i])
|
||||
s = s[i:]
|
||||
break
|
||||
}
|
||||
|
||||
// A valid U+FFFD still consumes one character of the limit.
|
||||
count++
|
||||
if count > limit {
|
||||
return s[:i]
|
||||
}
|
||||
}
|
||||
|
||||
// Fast-path, no invalid input.
|
||||
@@ -203,7 +387,9 @@ func truncate(limit int, s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// Truncate while validating UTF-8.
|
||||
// The builder holds the valid prefix before the first invalid byte, and
|
||||
// count includes its runes. Skip malformed bytes without counting them
|
||||
// while copying the remaining valid runes up to the limit.
|
||||
for i := 0; i < len(s) && count < limit; {
|
||||
c := s[i]
|
||||
if c < utf8.RuneSelf {
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ func NewSchemaless(attrs ...attribute.KeyValue) *Resource {
|
||||
return &Resource{}
|
||||
}
|
||||
|
||||
attrs, _ = attrnorm.KeyValues(attrs)
|
||||
attrs, _ = attrnorm.KeyValuesDedup(attrs)
|
||||
|
||||
// Ensure attributes comply with the specification:
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/common/README.md#attribute
|
||||
|
||||
Generated
Vendored
+6
@@ -47,6 +47,8 @@ type BSP struct {
|
||||
processedQueueFullOpts []metric.AddOption
|
||||
}
|
||||
|
||||
// NewBSP creates new instrumentation for a BatchSpanProcessor.
|
||||
// It returns nil if observability is not enabled.
|
||||
func NewBSP(id int64, qLen func() int64, qMax int64) (*BSP, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return nil, nil
|
||||
@@ -108,12 +110,16 @@ func NewBSP(id int64, qLen func() int64, qMax int64) (*BSP, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
// Shutdown unregisters the callbacks registered by NewBSP.
|
||||
func (b *BSP) Shutdown() error { return b.reg.Unregister() }
|
||||
|
||||
// Processed records n spans as having finished processing successfully.
|
||||
func (b *BSP) Processed(ctx context.Context, n int64) {
|
||||
b.processed.Add(ctx, n, b.processedOpts...)
|
||||
}
|
||||
|
||||
// ProcessedQueueFull records n spans as having finished processing with a
|
||||
// queue-full error.
|
||||
func (b *BSP) ProcessedQueueFull(ctx context.Context, n int64) {
|
||||
b.processed.Add(ctx, n, b.processedQueueFullOpts...)
|
||||
}
|
||||
+7
@@ -30,6 +30,8 @@ type Tracer struct {
|
||||
started metric.Int64Counter
|
||||
}
|
||||
|
||||
// NewTracer creates new instrumentation for a Tracer.
|
||||
// It returns an empty, disabled Tracer if observability is not enabled.
|
||||
func NewTracer() (Tracer, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return Tracer{}, nil
|
||||
@@ -52,8 +54,11 @@ func NewTracer() (Tracer, error) {
|
||||
return Tracer{enabled: true, live: l.Inst(), started: s.Inst()}, err
|
||||
}
|
||||
|
||||
// Enabled returns whether observability is enabled for t.
|
||||
func (t Tracer) Enabled() bool { return t.enabled }
|
||||
|
||||
// SpanStarted records the start of span, which was created with psc as its
|
||||
// parent span context.
|
||||
func (t Tracer) SpanStarted(ctx context.Context, psc trace.SpanContext, span trace.Span) {
|
||||
if !t.started.Enabled(ctx) {
|
||||
return
|
||||
@@ -84,10 +89,12 @@ func (t Tracer) SpanStarted(ctx context.Context, psc trace.SpanContext, span tra
|
||||
t.started.Add(ctx, 1, opts...)
|
||||
}
|
||||
|
||||
// SpanLive records span as a live span.
|
||||
func (t Tracer) SpanLive(ctx context.Context, span trace.Span) {
|
||||
t.spanLive(ctx, 1, span)
|
||||
}
|
||||
|
||||
// SpanEnded records span as no longer being live.
|
||||
func (t Tracer) SpanEnded(ctx context.Context, span trace.Span) {
|
||||
t.spanLive(ctx, -1, span)
|
||||
}
|
||||
|
||||
+48
-14
@@ -150,7 +150,10 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T
|
||||
return noop.NewTracerProvider().Tracer(name, opts...)
|
||||
}
|
||||
c := trace.NewTracerConfig(opts...)
|
||||
attrs, _ := attrnorm.Set(c.InstrumentationAttributes())
|
||||
attrs, _, _ := attrnorm.SetDedupLimitDepth(
|
||||
c.InstrumentationAttributes(),
|
||||
p.spanLimits.AttributeValueDepthLimit,
|
||||
)
|
||||
if name == "" {
|
||||
name = defaultTracerName
|
||||
}
|
||||
@@ -255,13 +258,14 @@ func (p *TracerProvider) UnregisterSpanProcessor(sp SpanProcessor) {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
if stopOnce != nil {
|
||||
stopOnce.state.Do(func() {
|
||||
if err := sp.Shutdown(context.Background()); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
})
|
||||
if stopOnce == nil {
|
||||
return
|
||||
}
|
||||
stopOnce.state.Do(func() {
|
||||
if err := sp.Shutdown(context.Background()); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
})
|
||||
if len(spss) > 1 {
|
||||
copy(spss[idx:], spss[idx+1:])
|
||||
}
|
||||
@@ -429,6 +433,29 @@ func WithSampler(s Sampler) TracerProviderOption {
|
||||
})
|
||||
}
|
||||
|
||||
// WithAttributeValueDepthLimit sets the maximum allowed depth for attribute
|
||||
// values. Depth starts at one for the top-level value and increments when
|
||||
// descending into an array element or map value. An array or map beyond this
|
||||
// depth is replaced by an empty value.
|
||||
//
|
||||
// This limit applies to span, event, link, and instrumentation scope
|
||||
// attributes processed by this TracerProvider. It does not apply to Resource
|
||||
// attributes.
|
||||
//
|
||||
// Setting this to zero means the default limit of 64 is used. Setting this to
|
||||
// a negative value means no limit is applied.
|
||||
//
|
||||
// There is no environment variable for this limit.
|
||||
func WithAttributeValueDepthLimit(limit int) TracerProviderOption {
|
||||
if limit == 0 {
|
||||
limit = DefaultAttributeValueDepthLimit
|
||||
}
|
||||
return traceProviderOptionFunc(func(cfg tracerProviderConfig) tracerProviderConfig {
|
||||
cfg.spanLimits.AttributeValueDepthLimit = limit
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
// WithSpanLimits returns a TracerProviderOption that configures a
|
||||
// TracerProvider to use the SpanLimits sl. These SpanLimits bound any Span
|
||||
// created by a Tracer from the TracerProvider.
|
||||
@@ -448,6 +475,9 @@ func WithSpanLimits(sl SpanLimits) TracerProviderOption {
|
||||
if sl.AttributeValueLengthLimit <= 0 {
|
||||
sl.AttributeValueLengthLimit = DefaultAttributeValueLengthLimit
|
||||
}
|
||||
if sl.AttributeValueDepthLimit <= 0 {
|
||||
sl.AttributeValueDepthLimit = DefaultAttributeValueDepthLimit
|
||||
}
|
||||
if sl.AttributeCountLimit <= 0 {
|
||||
sl.AttributeCountLimit = DefaultAttributeCountLimit
|
||||
}
|
||||
@@ -473,13 +503,14 @@ func WithSpanLimits(sl SpanLimits) TracerProviderOption {
|
||||
// TracerProvider to use these limits. These limits bound any Span created by
|
||||
// a Tracer from the TracerProvider.
|
||||
//
|
||||
// The limits will be used as-is. Zero or negative values will not be changed
|
||||
// to the default value like WithSpanLimits does. Setting a limit to zero will
|
||||
// effectively disable the related resource it limits and setting to a
|
||||
// negative value will mean that resource is unlimited. Consequentially, this
|
||||
// means that the zero-value SpanLimits will disable all span resources.
|
||||
// Because of this, limits should be constructed using NewSpanLimits and
|
||||
// updated accordingly.
|
||||
// The limits will be used as-is, except that an AttributeValueDepthLimit of
|
||||
// zero means the default limit is used. Other zero or negative values will not
|
||||
// be changed to the default value like WithSpanLimits does. Setting a limit to
|
||||
// zero will effectively disable the related resource it limits and setting to
|
||||
// a negative value will mean that resource is unlimited. Consequentially, the
|
||||
// zero-value SpanLimits will disable all span resources except the attribute
|
||||
// value depth limit. Because of this, limits should be constructed using
|
||||
// NewSpanLimits and updated accordingly.
|
||||
//
|
||||
// If this or WithSpanLimits are not provided, the TracerProvider will use the
|
||||
// limits defined by environment variables, or the defaults if unset. Refer to
|
||||
@@ -525,5 +556,8 @@ func ensureValidTracerProviderConfig(cfg tracerProviderConfig) tracerProviderCon
|
||||
if cfg.resource == nil {
|
||||
cfg.resource = resource.Default()
|
||||
}
|
||||
if cfg.spanLimits.AttributeValueDepthLimit == 0 {
|
||||
cfg.spanLimits.AttributeValueDepthLimit = DefaultAttributeValueDepthLimit
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
+4
-5
@@ -46,14 +46,13 @@ func (e samplerArgParseError) Unwrap() error {
|
||||
}
|
||||
|
||||
func samplerFromEnv() (Sampler, error) {
|
||||
sampler, ok := os.LookupEnv(tracesSamplerKey)
|
||||
if !ok {
|
||||
sampler := strings.ToLower(strings.TrimSpace(os.Getenv(tracesSamplerKey)))
|
||||
if sampler == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sampler = strings.ToLower(strings.TrimSpace(sampler))
|
||||
samplerArg, hasSamplerArg := os.LookupEnv(tracesSamplerArgKey)
|
||||
samplerArg = strings.TrimSpace(samplerArg)
|
||||
samplerArg := strings.TrimSpace(os.Getenv(tracesSamplerArgKey))
|
||||
hasSamplerArg := samplerArg != ""
|
||||
|
||||
switch sampler {
|
||||
case samplerAlwaysOn:
|
||||
|
||||
+6
-1
@@ -104,10 +104,15 @@ func (ssp *simpleSpanProcessor) Shutdown(ctx context.Context) error {
|
||||
// span would need to be exported. Meaning, OnEnd would be called and
|
||||
// try acquiring the lock that is held here.
|
||||
ssp.exporterMu.Lock()
|
||||
done, shutdown := stopFunc(ssp.exporter)
|
||||
exp := ssp.exporter
|
||||
ssp.exporter = nil
|
||||
ssp.exporterMu.Unlock()
|
||||
|
||||
if exp == nil {
|
||||
return
|
||||
}
|
||||
|
||||
done, shutdown := stopFunc(exp)
|
||||
go shutdown()
|
||||
|
||||
// Wait for the exporter to shut down or the deadline to expire.
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// snapshot is an record of a spans state at a particular checkpointed time.
|
||||
// snapshot is a record of a span's state at a particular checkpointed time.
|
||||
// It is used as a read-only representation of that state.
|
||||
type snapshot struct {
|
||||
name string
|
||||
|
||||
+33
-18
@@ -278,8 +278,11 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) {
|
||||
s.addDroppedAttr(1)
|
||||
continue
|
||||
}
|
||||
a = dedupAttr(a)
|
||||
a = attrnorm.Truncate(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
|
||||
a = normAttr(
|
||||
a,
|
||||
s.tracer.provider.spanLimits.AttributeValueDepthLimit,
|
||||
s.tracer.provider.spanLimits.AttributeValueLengthLimit,
|
||||
)
|
||||
s.attributes = append(s.attributes, a)
|
||||
s.attributesDirty = true
|
||||
}
|
||||
@@ -353,8 +356,11 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {
|
||||
|
||||
if idx, ok := exists[a.Key]; ok {
|
||||
// Perform all updates before dropping, even when at capacity.
|
||||
a = dedupAttr(a)
|
||||
a = attrnorm.Truncate(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
|
||||
a = normAttr(
|
||||
a,
|
||||
s.tracer.provider.spanLimits.AttributeValueDepthLimit,
|
||||
s.tracer.provider.spanLimits.AttributeValueLengthLimit,
|
||||
)
|
||||
s.attributes[idx] = a
|
||||
continue
|
||||
}
|
||||
@@ -364,22 +370,27 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {
|
||||
// updates are checked and performed.
|
||||
s.addDroppedAttr(1)
|
||||
} else {
|
||||
a = dedupAttr(a)
|
||||
a = attrnorm.Truncate(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
|
||||
a = normAttr(
|
||||
a,
|
||||
s.tracer.provider.spanLimits.AttributeValueDepthLimit,
|
||||
s.tracer.provider.spanLimits.AttributeValueLengthLimit,
|
||||
)
|
||||
s.attributes = append(s.attributes, a)
|
||||
exists[a.Key] = len(s.attributes) - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func dedupAttr(attr attribute.KeyValue) attribute.KeyValue {
|
||||
func normAttr(attr attribute.KeyValue, depthLimit, lengthLimit int) attribute.KeyValue {
|
||||
switch attr.Value.Type() {
|
||||
case attribute.SLICE, attribute.MAP:
|
||||
attr, _ = attrnorm.KeyValue(attr)
|
||||
return attr
|
||||
default:
|
||||
return attr
|
||||
if depthLimit < 0 {
|
||||
attr, _ = attrnorm.KeyValueDedup(attr)
|
||||
} else {
|
||||
attr, _, _ = attrnorm.KeyValueDedupLimitDepth(attr, depthLimit)
|
||||
}
|
||||
}
|
||||
return attrnorm.Truncate(lengthLimit, attr)
|
||||
}
|
||||
|
||||
// End ends the span. This method does nothing if the span is already ended or
|
||||
@@ -483,9 +494,7 @@ func (s *recordingSpan) RecordError(err error, opts ...trace.EventOption) {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !s.isRecording() {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -501,7 +510,7 @@ func (s *recordingSpan) RecordError(err error, opts ...trace.EventOption) {
|
||||
))
|
||||
}
|
||||
|
||||
s.addEvent(semconv.ExceptionEventName, opts...)
|
||||
s.AddEvent(semconv.ExceptionEventName, opts...)
|
||||
}
|
||||
|
||||
func typeStr(i any) string {
|
||||
@@ -540,7 +549,10 @@ func (s *recordingSpan) AddEvent(name string, o ...trace.EventOption) {
|
||||
// This method assumes s.mu.Lock is held by the caller.
|
||||
func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) {
|
||||
c := trace.NewEventConfig(o...)
|
||||
attrs, _ := attrnorm.KeyValues(c.Attributes())
|
||||
attrs, _, _ := attrnorm.KeyValuesDedupLimitDepth(
|
||||
c.Attributes(),
|
||||
s.tracer.provider.spanLimits.AttributeValueDepthLimit,
|
||||
)
|
||||
e := Event{Name: name, Attributes: attrs, Time: c.Timestamp()}
|
||||
|
||||
// Discard attributes over limit.
|
||||
@@ -580,7 +592,7 @@ func (s *recordingSpan) Name() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
// Name returns the SpanContext of this span's parent span.
|
||||
// Parent returns the SpanContext of this span's parent span.
|
||||
func (s *recordingSpan) Parent() trace.SpanContext {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
@@ -720,7 +732,10 @@ func (s *recordingSpan) AddLink(link trace.Link) {
|
||||
return
|
||||
}
|
||||
|
||||
attrs, _ := attrnorm.KeyValues(link.Attributes)
|
||||
attrs, _, _ := attrnorm.KeyValuesDedupLimitDepth(
|
||||
link.Attributes,
|
||||
s.tracer.provider.spanLimits.AttributeValueDepthLimit,
|
||||
)
|
||||
l := Link{SpanContext: link.SpanContext, Attributes: attrs}
|
||||
|
||||
// Discard attributes over limit.
|
||||
|
||||
+24
-2
@@ -10,6 +10,10 @@ const (
|
||||
// attribute value length, unlimited.
|
||||
DefaultAttributeValueLengthLimit = -1
|
||||
|
||||
// DefaultAttributeValueDepthLimit is the default maximum allowed depth for
|
||||
// nested attribute values.
|
||||
DefaultAttributeValueDepthLimit = 64
|
||||
|
||||
// DefaultAttributeCountLimit is the default maximum number of attributes
|
||||
// a span can have.
|
||||
DefaultAttributeCountLimit = 128
|
||||
@@ -43,6 +47,20 @@ type SpanLimits struct {
|
||||
// Setting this to a negative value means no limit is applied.
|
||||
AttributeValueLengthLimit int
|
||||
|
||||
// AttributeValueDepthLimit is the maximum allowed depth for an attribute
|
||||
// value. Depth starts at one for the top-level value and increments when
|
||||
// descending into an array element or map value. An array or map beyond this
|
||||
// depth is replaced by an empty value.
|
||||
//
|
||||
// This limit applies to span, event, link, and instrumentation scope
|
||||
// attributes processed by a TracerProvider. It does not apply to Resource
|
||||
// attributes.
|
||||
//
|
||||
// Setting this to zero means the default limit is used.
|
||||
//
|
||||
// Setting this to a negative value means no limit is applied.
|
||||
AttributeValueDepthLimit int
|
||||
|
||||
// AttributeCountLimit is the maximum allowed span attribute count. Any
|
||||
// attribute added to a span once this limit is reached will be dropped.
|
||||
//
|
||||
@@ -88,12 +106,15 @@ type SpanLimits struct {
|
||||
AttributePerLinkCountLimit int
|
||||
}
|
||||
|
||||
// NewSpanLimits returns a SpanLimits with all limits set to the value their
|
||||
// corresponding environment variable holds, or the default if unset.
|
||||
// NewSpanLimits returns a SpanLimits with all limits set to their default.
|
||||
// Limits with a corresponding environment variable are set from the
|
||||
// environment when the variable is defined.
|
||||
//
|
||||
// • AttributeValueLengthLimit: OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT
|
||||
// (default: unlimited)
|
||||
//
|
||||
// • AttributeValueDepthLimit: default 64 (no environment variable)
|
||||
//
|
||||
// • AttributeCountLimit: OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT (default: 128)
|
||||
//
|
||||
// • EventCountLimit: OTEL_SPAN_EVENT_COUNT_LIMIT (default: 128)
|
||||
@@ -107,6 +128,7 @@ type SpanLimits struct {
|
||||
func NewSpanLimits() SpanLimits {
|
||||
return SpanLimits{
|
||||
AttributeValueLengthLimit: env.SpanAttributeValueLength(DefaultAttributeValueLengthLimit),
|
||||
AttributeValueDepthLimit: DefaultAttributeValueDepthLimit,
|
||||
AttributeCountLimit: env.SpanAttributeCount(DefaultAttributeCountLimit),
|
||||
EventCountLimit: env.SpanEventCount(DefaultEventCountLimit),
|
||||
LinkCountLimit: env.SpanLinkCount(DefaultLinkCountLimit),
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ package sdk
|
||||
|
||||
// Version is the current release version of the OpenTelemetry SDK in use.
|
||||
func Version() string {
|
||||
return "1.46.0"
|
||||
return "1.47.0"
|
||||
}
|
||||
+12
-2
@@ -372,7 +372,7 @@ func convAttrValue(value attribute.Value) telemetry.Value {
|
||||
return telemetry.Value{}
|
||||
}
|
||||
|
||||
// truncate returns a truncated version of s such that it contains less than
|
||||
// truncate returns a truncated version of s such that it contains at most
|
||||
// the limit number of characters. Truncation is applied by returning the limit
|
||||
// number of valid characters contained in s.
|
||||
//
|
||||
@@ -381,7 +381,7 @@ func convAttrValue(value attribute.Value) telemetry.Value {
|
||||
// UTF-8 is supported. When truncating, all invalid characters are dropped
|
||||
// before applying truncation.
|
||||
//
|
||||
// If s already contains less than the limit number of bytes, it is returned
|
||||
// If s already contains at most the limit number of bytes, it is returned
|
||||
// unchanged. No invalid characters are removed.
|
||||
func truncate(limit int, s string) string {
|
||||
// This prioritize performance in the following order based on the most
|
||||
@@ -407,6 +407,10 @@ func truncate(limit int, s string) string {
|
||||
continue
|
||||
}
|
||||
|
||||
// A zero limit also truncates a leading invalid byte or U+FFFD.
|
||||
if limit == 0 {
|
||||
return ""
|
||||
}
|
||||
_, size := utf8.DecodeRuneInString(s[i:])
|
||||
if size == 1 {
|
||||
// Invalid encoding.
|
||||
@@ -415,6 +419,12 @@ func truncate(limit int, s string) string {
|
||||
s = s[i:]
|
||||
break
|
||||
}
|
||||
|
||||
// A valid U+FFFD still consumes one character of the limit.
|
||||
count++
|
||||
if count > limit {
|
||||
return s[:i]
|
||||
}
|
||||
}
|
||||
|
||||
// Fast-path, no invalid input.
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ func (i *protoInt64) UnmarshalJSON(data []byte) error {
|
||||
// strings or integers.
|
||||
type protoUint64 uint64
|
||||
|
||||
// Int64 returns the protoUint64 as a uint64.
|
||||
// Uint64 returns the protoUint64 as a uint64.
|
||||
func (i *protoUint64) Uint64() uint64 { return uint64(*i) }
|
||||
|
||||
// UnmarshalJSON decodes both strings and integers.
|
||||
|
||||
Loaded 100 of 106 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user