Stephen Kitt committed 2026-10-07 16:33:41 +02:00
1 parent 841d8db723
commit 0180ae4efd
106 files changed
+3936 -766

No files matched your search

+234
View File
@@ -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
+10 -9
View File
@@ -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
+26 -24
View File
@@ -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=
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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=
+9 -8
View File
@@ -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
)
+20 -18
View File
@@ -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=
+9 -8
View File
@@ -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
+20 -18
View File
@@ -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=
+8 -7
View File
@@ -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
+18 -16
View File
@@ -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=
+9 -8
View File
@@ -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
View File
@@ -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=
+1 -1
View File
@@ -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
)
+2 -2
View File
@@ -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=
+7 -6
View File
@@ -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 (
+18 -16
View File
@@ -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=
+1 -1
View File
@@ -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
)
+2 -2
View File
@@ -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
View File
@@ -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=
+2 -2
View File
@@ -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
+10 -9
View File
@@ -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=
+1 -1
View File
@@ -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
)
+2 -2
View File
@@ -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=
+1 -1
View File
@@ -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
)
+2 -2
View File
@@ -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
View File
@@ -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=
+9 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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=
+10 -9
View File
@@ -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=
+8 -7
View File
@@ -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=
+8 -7
View File
@@ -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=
+1 -1
View File
@@ -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
+11 -10
View File
@@ -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
View File
@@ -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=
+9 -8
View File
@@ -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
View File
@@ -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=
@@ -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)
@@ -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"
@@ -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"
@@ -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
@@ -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 {
@@ -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,
@@ -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)
@@ -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
}
@@ -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()
}
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,3 +0,0 @@
# Instructions for Claude Code
@AGENTS.md
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -3,12 +3,11 @@
[![ci](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml)
[![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-go/coverage.svg?branch=main)](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main)
[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel)](https://pkg.go.dev/go.opentelemetry.io/otel)
[![Go Report Card](https://goreportcard.com/badge/go.opentelemetry.io/otel)](https://goreportcard.com/report/go.opentelemetry.io/otel)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/open-telemetry/opentelemetry-go/badge)](https://scorecard.dev/viewer/?uri=github.com/open-telemetry/opentelemetry-go)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9996/badge)](https://www.bestpractices.dev/projects/9996)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/opentelemetry-go.svg)](https://issues.oss-fuzz.com/issues?q=project:opentelemetry-go)
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-go.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-go?ref=badge_shield&issueType=license)
[![Slack](https://img.shields.io/badge/slack-@cncf/otel--go-brightgreen.svg?logo=slack)](https://cloud-native.slack.com/archives/C01NPAXACKT)
[![Slack](https://img.shields.io/badge/slack-@cncf/otel--go-brightgreen.svg?logo=slack)](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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -0,0 +1,3 @@
# Log API
[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/log)](https://pkg.go.dev/go.opentelemetry.io/otel/log)
+85
View File
@@ -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
View File
@@ -0,0 +1,3 @@
# Log Embedded
[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/log/embedded)](https://pkg.go.dev/go.opentelemetry.io/otel/log/embedded)
+36
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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