diff --git a/README.md b/README.md
index 989b7c1fa..179f1ca32 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ With GoToSocial, you can keep in touch with your friends, post, read, and share
-**GoToSocial is still [ALPHA SOFTWARE](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha)**. It is already deployable and useable, and it federates cleanly with many other Fediverse servers (not yet all). However, many things are not yet implemented, and there are plenty of bugs! We foresee entering beta around the beginning of 2024.
+**GoToSocial is still [BETA SOFTWARE](https://en.wikipedia.org/wiki/Software_release_life_cycle#Beta)**. It is already deployable and useable, and it federates cleanly with many other Fediverse servers (not yet all). However, many things are not yet implemented, and there are plenty of bugs! We left alpha stage around September/October 2024, and we intend to exit beta some time around 2026.
Documentation is at [docs.gotosocial.org](https://docs.gotosocial.org). You can skip straight to the API documentation [here](https://docs.gotosocial.org/en/latest/api/swagger/).
@@ -29,8 +29,12 @@ Here's a screenshot of the instance landing page!
- [History and Status](#history-and-status)
- [Features](#features)
- [Mastodon API compatibility](#mastodon-api-compatibility)
- - [Granular post settings](#granular-post-settings)
- - [Customizability](#customizability)
+ - [Granular post visibility settings](#granular-post-visibility-settings)
+ - [Reply controls](#reply-controls)
+ - [Local-only posting](#local-only-posting)
+ - [RSS feed](#rss-feed)
+ - [Rich text formatting](#rich-text-formatting)
+ - [Themes and custom CSS](#themes-and-custom-css)
- [Easy to run](#easy-to-run)
- [Safety + security features](#safety--security-features)
- [Various federation modes](#various-federation-modes)
@@ -90,7 +94,9 @@ This project sprang up in February/March 2021 out of a dissatisfaction with the
It began as a solo project, and then picked up steam as more developers became interested and jumped on.
-For a detailed view on what's implemented and what's not, and progress made towards [beta release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Beta), please see [the roadmap document](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md).
+We made our first Alpha release in November 2021. We left Alpha and entered Beta in September/October 2024.
+
+For a detailed view on what's implemented and what's not, and progress made towards [stable release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Stable_release), please see [the roadmap document](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md).
---
@@ -100,44 +106,120 @@ For a detailed view on what's implemented and what's not, and progress made towa
The Mastodon API has become the de facto standard for client communication with federated servers, so GoToSocial has implemented and extended the API with custom functionality.
-Though most apps that implement the Mastodon API should work, GoToSocial works reliably with beautiful apps like:
+Though most apps that implement the Mastodon API should work, GoToSocial is tested and works reliably with beautiful apps like:
* [Tusky](https://tusky.app/) for Android
* [Semaphore](https://semaphore.social/) in the browser
* [Feditext](https://github.com/feditext/feditext) (beta) on iOS, iPadOS and macOS
-If you've used Mastodon with any of these apps before, you'll find using GoToSocial a breeze.
+If you've used Mastodon with a third-party app before, you'll find using GoToSocial a breeze.
-### Granular post settings
+### Granular post visibility settings
It's important that when you post something, you can choose who sees it.
-GoToSocial offers public/unlisted/friends-only/mutuals-only/and direct posts (slide in DMs! -- with consent).
+GoToSocial offers public, unlisted/unlocked, followers-only, and direct posts (slide in DMs! -- with consent).
-It also allows you to customize how people interact with your posts:
+### Reply controls
-- Local-only posts.
-- Rebloggable/boostable toggle.
-- 'Likeable' toggle.
-- 'Replyable' toggle.
+GoToSocial lets you choose who can reply to your posts, via [interaction policies](https://docs.gotosocial.org/en/latest/user_guide/settings/#default-interaction-policies). You can choose to let anyone reply to your posts, let only your friends reply, and more.
-### Customizability
+![interaction policies settings](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/docs/assets/user-settings-interaction-policy-1.png)
+
+### Local-only posting
+
+Sometimes you only want to talk to people you share an instance with. GoToSocial supports this via local-only posting, which ensures that your post stays on your instance only. (Local-only posting is currently dependent on client support.)
+
+### RSS feed
+
+GoToSocial lets you opt-in to exposing your profile as an RSS feed, so that people can subscribe to your public feed without missing a post.
+
+### Rich text formatting
+
+With GoToSocial, you can write posts using the popular, easy-to-use Markdown markup language, which lets you produce rich HTML posts with support for blockquotes, syntax-highlighted code blocks, lists, inline links, and more.
+
+![markdown-formatted post](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/docs/assets/markdown-post.png)
+
+### Themes and custom CSS
Users can [choose from a variety of fun themes](https://docs.gotosocial.org/en/latest/user_guide/settings/#select-theme) for their profile, or even write their own [custom CSS](https://docs.gotosocial.org/en/latest/user_guide/settings/#custom-css).
-Plenty of [config options](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml) for admins to play around with too.
+It's also easy for admins to [add their own custom themes](https://docs.gotosocial.org/en/latest/admin/themes/) for users to choose from.
+
+
+Show theme examples
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
### Easy to run
-No external dependencies apart from a database (or just use SQLite!). Simply download the binary + assets (or Docker container), and run.
+GoToSocial uses only about 250-350MiB of RAM, and requires very little CPU power, so it plays nice with single-board computers, old laptops and tiny $5/month VPSes.
-GoToSocial uses only about 150-250MiB of RAM, so it plays nice with single-board computers, old laptops and tiny $5/month VPSes.
+![Grafana graph showing GoToSocial heap in use hovering around 250MB and spiking occasionally to 400MB-500MB.](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/docs/assets/getting-started-memory-graph.png)
+
+No external dependencies apart from a database (or just use SQLite!).
+
+Simply download the binary + assets (or Docker container), tweak your configuration, and run.
### Safety + security features
- Built-in, automatic support for secure HTTPS with [Let's Encrypt](https://letsencrypt.org/).
- Strict privacy enforcement for posts and strict blocking logic.
-- Import and export allow lists and deny lists. Subscribe to community-created block lists (think Ad blocker, but for federation!).
+- Import and export allow lists and deny lists. Subscribe to community-created block lists (think Ad blocker, but for federation!) (feature still in progress).
- HTTP signature authentication: GoToSocial requires [HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12) when sending and receiving messages, to ensure that your messages can't be tampered with and your identity can't be forged.
### Various federation modes
@@ -166,7 +248,7 @@ On top of this API, web developers are encouraged to build any front-end impleme
## Known Issues
-Since GoToSocial is still in alpha, there are plenty of bugs. We use [GitHub issues](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) to track these.
+Since GoToSocial is still in beta, there are plenty of bugs. We use [GitHub issues](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) to track these.
Since every ActivityPub server implementation has a slightly different interpretation of the protocol, some servers don't quite federate properly with GoToSocial yet. We're tracking these issues [in this project](https://github.com/superseriousbusiness/gotosocial/projects/4). Eventually, we want to make sure that any implementation that can federate nicely with Mastodon should also be able to federate with GoToSocial.
diff --git a/ROADMAP.md b/ROADMAP.md
index f7af8ce92..a4894f4fe 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,10 +1,10 @@
# Roadmap to Beta
-This document contains the roadmap for GoToSocial to be considered eligible for its first [beta release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Beta).
+This document contains the roadmap for GoToSocial to be considered eligible for its first proper [stable release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Stable_release).
All the info contained in this document is best-guess only. It's useful to have a rough timeline we can direct people to, but things will undoubtedly change along the way; don't hold us to anything in this doc!
-Thank you to [NLnet](https://nlnet.nl) for helping to fund the alpha phase of GoToSocial development and get us moving towards beta!
+Thank you to [NLnet](https://nlnet.nl) for helping to fund the alpha and beta phases of GoToSocial development!
Big thank you to all of our [Open Collective](https://opencollective.com/gotosocial) and [Liberapay](https://liberapay.com/gotosocial) contributors, who've helped us keep the lights on! đ
@@ -17,6 +17,7 @@ Big thank you to all of our [Open Collective](https://opencollective.com/gotosoc
- [Early 2024](#early-2024)
- [BETA milestone](#beta-milestone)
- [Remainder 2024 - early 2025](#remainder-2024---early-2025)
+ - [On the way out of BETA to STABLE RELEASE](#on-the-way-out-of-beta-to-stable-release)
- [Wishlist](#wishlist)
## Beta Aims
@@ -61,7 +62,7 @@ What follows is a rough timeline of features that will be implemented on the roa
### BETA milestone
-Completion of all above features indicates that we are now in the BETA phase of GoToSocial. We foresee this happening around Feb/March 2024.
+Completion of all above features indicates that we are now in the BETA phase of GoToSocial. We foresee this happening around Feb/March 2024. EDIT: It ended up happening in September/October 2024, whoops!
### Remainder 2024 - early 2025
@@ -69,9 +70,9 @@ These are provided in no specific order.
- [x] **Filters v2** -- implement v2 of the filters API.
- [x] **Mute accounts** -- mute accounts to prevent their posts showing up in your home timeline (optional: for limited period of time).
-- [ ] **Non-replyable posts** -- design a non-replyable post path for GoToSocial based on https://github.com/mastodon/mastodon/issues/14762#issuecomment-1196889788; allow users to create non-replyable posts.
+- [x] **Non-replyable posts** -- design a non-replyable post path for GoToSocial based on https://github.com/mastodon/mastodon/issues/14762#issuecomment-1196889788; allow users to create non-replyable posts.
- [ ] **Block + allow list subscriptions** -- allow instance admins to subscribe their instance to plaintext domain block/allow lists (much of the work for this is already in place).
-- [ ] **Direct conversation view** -- allow users to easily page through all direct-message conversations they're a part of.
+- [x] **Direct conversation view** -- allow users to easily page through all direct-message conversations they're a part of.
- [ ] **Oauth token management** -- create / view / invalidate OAuth tokens via the settings panel.
- [ ] **Status EDIT support** -- edit statuses that you've created, without having to delete + redraft. Federate edits out properly.
- [ ] **Fediverse relay support** -- publish posts to relays, pull posts from relays.
@@ -80,6 +81,10 @@ These are provided in no specific order.
More tbd!
+### On the way out of BETA to STABLE RELEASE
+
+Tbd.
+
## Wishlist
These cool things will be implemented if time allows (because we really want them):
diff --git a/docs/assets/getting-started-memory-graph.png b/docs/assets/getting-started-memory-graph.png
index 2a5bf1c17..79fceff4d 100644
Binary files a/docs/assets/getting-started-memory-graph.png and b/docs/assets/getting-started-memory-graph.png differ
diff --git a/docs/assets/markdown-post.png b/docs/assets/markdown-post.png
new file mode 100644
index 000000000..750f36e49
Binary files /dev/null and b/docs/assets/markdown-post.png differ
diff --git a/docs/assets/theme-blurple-dark.png b/docs/assets/theme-blurple-dark.png
new file mode 100644
index 000000000..8a0c47aec
Binary files /dev/null and b/docs/assets/theme-blurple-dark.png differ
diff --git a/docs/assets/theme-blurple-light.png b/docs/assets/theme-blurple-light.png
new file mode 100644
index 000000000..51f6110d7
Binary files /dev/null and b/docs/assets/theme-blurple-light.png differ
diff --git a/docs/assets/theme-brutalist-dark.png b/docs/assets/theme-brutalist-dark.png
new file mode 100644
index 000000000..14e4c637c
Binary files /dev/null and b/docs/assets/theme-brutalist-dark.png differ
diff --git a/docs/assets/theme-brutalist-light.png b/docs/assets/theme-brutalist-light.png
new file mode 100644
index 000000000..980134e1e
Binary files /dev/null and b/docs/assets/theme-brutalist-light.png differ
diff --git a/docs/assets/theme-ecks-pee.png b/docs/assets/theme-ecks-pee.png
new file mode 100644
index 000000000..73e8bb9a8
Binary files /dev/null and b/docs/assets/theme-ecks-pee.png differ
diff --git a/docs/assets/theme-midnight-trip.png b/docs/assets/theme-midnight-trip.png
new file mode 100644
index 000000000..05e557be8
Binary files /dev/null and b/docs/assets/theme-midnight-trip.png differ
diff --git a/docs/assets/theme-rainforest.png b/docs/assets/theme-rainforest.png
new file mode 100644
index 000000000..1694d7417
Binary files /dev/null and b/docs/assets/theme-rainforest.png differ
diff --git a/docs/assets/theme-soft.png b/docs/assets/theme-soft.png
new file mode 100644
index 000000000..7b094fcde
Binary files /dev/null and b/docs/assets/theme-soft.png differ
diff --git a/docs/assets/theme-solarized-dark.png b/docs/assets/theme-solarized-dark.png
new file mode 100644
index 000000000..468ab8534
Binary files /dev/null and b/docs/assets/theme-solarized-dark.png differ
diff --git a/docs/assets/theme-solarized-light.png b/docs/assets/theme-solarized-light.png
new file mode 100644
index 000000000..ded2a2db7
Binary files /dev/null and b/docs/assets/theme-solarized-light.png differ
diff --git a/docs/assets/theme-sunset.png b/docs/assets/theme-sunset.png
new file mode 100644
index 000000000..a2361b437
Binary files /dev/null and b/docs/assets/theme-sunset.png differ
diff --git a/docs/faq.md b/docs/faq.md
index 546c2064a..521c97531 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -36,6 +36,6 @@ To see posts, you have to start following people! Once you've followed a few peo
We introduced a sign-up flow in v0.16.0. The server you want to sign up to must have enabled registrations/sign-ups, as detailed [right here](./admin/signups.md).
-## Why's it still in alpha?
+## Why's it still in Beta?
Take a look at the [list of open bugs](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and the [roadmap](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md) for a more detailed rundown.
diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md
index 95dcb8e22..cd79cb312 100644
--- a/docs/getting_started/index.md
+++ b/docs/getting_started/index.md
@@ -20,7 +20,7 @@ You can find more detail on system requirements below, but in short you should a
For a small instance (1-20 active users), GoToSocial will likely hover consistently between 250MB and 350MB of RAM usage once the internal caches are hydrated:
-![Grafana graph showing GoToSocial heap in use hovering around 300MB and spiking occasionally to 400MB-500MB.](../assets/getting-started-memory-graph.png)
+![Grafana graph showing GoToSocial heap in use hovering around 250MB and spiking occasionally to 400MB-500MB.](../assets/getting-started-memory-graph.png)
In the graph above you can see that RAM usage spikes during periods of load. This happens, for example, when when a status gets boosted by someone with many followers, or when the embedded `ffmpeg` binary is decoding or reencoding media files into thumbnails (especially larger video files).
diff --git a/go.mod b/go.mod
index e14990b14..6a5b467b7 100644
--- a/go.mod
+++ b/go.mod
@@ -46,7 +46,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/ncruces/go-sqlite3 v0.18.3
github.com/oklog/ulid v1.3.1
- github.com/prometheus/client_golang v1.20.3
+ github.com/prometheus/client_golang v1.20.4
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
@@ -64,14 +64,14 @@ require (
github.com/uptrace/bun/extra/bunotel v1.2.1
github.com/wagslane/go-password-validator v0.3.0
github.com/yuin/goldmark v1.7.4
- go.opentelemetry.io/otel v1.30.0
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0
- go.opentelemetry.io/otel/exporters/prometheus v0.52.0
- go.opentelemetry.io/otel/metric v1.30.0
- go.opentelemetry.io/otel/sdk v1.30.0
- go.opentelemetry.io/otel/sdk/metric v1.30.0
- go.opentelemetry.io/otel/trace v1.30.0
+ go.opentelemetry.io/otel v1.29.0
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0
+ go.opentelemetry.io/otel/exporters/prometheus v0.51.0
+ go.opentelemetry.io/otel/metric v1.29.0
+ go.opentelemetry.io/otel/sdk v1.29.0
+ go.opentelemetry.io/otel/sdk/metric v1.29.0
+ go.opentelemetry.io/otel/trace v1.29.0
go.uber.org/automaxprocs v1.5.3
golang.org/x/crypto v0.27.0
golang.org/x/image v0.20.0
@@ -208,7 +208,7 @@ require (
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.8.0 // indirect
diff --git a/go.sum b/go.sum
index 3c9d29dc7..148a74915 100644
--- a/go.sum
+++ b/go.sum
@@ -468,8 +468,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
-github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
-github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
+github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
@@ -638,24 +638,24 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
-go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 h1:umZgi92IyxfXd/l4kaDhnKgY8rnN/cZcF1LKc6I8OQ8=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0/go.mod h1:4lVs6obhSVRb1EW5FhOuBTyiQhtRtAnnva9vD3yRfq8=
-go.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ=
-go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0=
-go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
-go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
-go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
-go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
-go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM=
-go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y=
-go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
-go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
+go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
+go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc=
+go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw=
+go.opentelemetry.io/otel/exporters/prometheus v0.51.0/go.mod h1:v0mFe5Kk7woIh938mrZBJBmENYquyA0IICrlYm4Y0t4=
+go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
+go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
+go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
+go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
+go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY=
+go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ=
+go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
+go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
diff --git a/internal/api/client/statuses/status_test.go b/internal/api/client/statuses/status_test.go
index a979f0c00..1a92276a1 100644
--- a/internal/api/client/statuses/status_test.go
+++ b/internal/api/client/statuses/status_test.go
@@ -18,6 +18,12 @@
package statuses_test
import (
+ "bytes"
+ "encoding/json"
+ "io"
+ "net/http/httptest"
+ "strings"
+
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/api/client/statuses"
"github.com/superseriousbusiness/gotosocial/internal/db"
@@ -25,6 +31,7 @@
"github.com/superseriousbusiness/gotosocial/internal/federation"
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/internal/id"
"github.com/superseriousbusiness/gotosocial/internal/media"
"github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/state"
@@ -59,6 +66,113 @@ type StatusStandardTestSuite struct {
statusModule *statuses.Module
}
+// Normalizes a status response to a determinate
+// form, and pretty-prints it to JSON.
+func (suite *StatusStandardTestSuite) parseStatusResponse(
+ recorder *httptest.ResponseRecorder,
+) (string, *httptest.ResponseRecorder) {
+
+ result := recorder.Result()
+ defer result.Body.Close()
+
+ data, err := io.ReadAll(result.Body)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ rawMap := make(map[string]any)
+ if err := json.Unmarshal(data, &rawMap); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // Make status fields determinate.
+ suite.determinateStatus(rawMap)
+
+ // For readability, don't
+ // escape HTML, and indent json.
+ out := new(bytes.Buffer)
+ enc := json.NewEncoder(out)
+ enc.SetEscapeHTML(false)
+ enc.SetIndent("", " ")
+
+ if err := enc.Encode(&rawMap); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ return strings.TrimSpace(out.String()), recorder
+}
+
+func (suite *StatusStandardTestSuite) determinateStatus(rawMap map[string]any) {
+ // Replace any fields from the raw map that
+ // aren't determinate (date, id, url, etc).
+ if _, ok := rawMap["id"]; ok {
+ rawMap["id"] = id.Highest
+ }
+
+ if _, ok := rawMap["uri"]; ok {
+ rawMap["uri"] = "http://localhost:8080/some/determinate/url"
+ }
+
+ if _, ok := rawMap["url"]; ok {
+ rawMap["url"] = "http://localhost:8080/some/determinate/url"
+ }
+
+ if _, ok := rawMap["created_at"]; ok {
+ rawMap["created_at"] = "right the hell just now babyee"
+ }
+
+ // Make ID of any mentions determinate.
+ if menchiesRaw, ok := rawMap["mentions"]; ok {
+ menchies, ok := menchiesRaw.([]any)
+ if !ok {
+ suite.FailNow("couldn't coerce menchies")
+ }
+
+ for _, menchieRaw := range menchies {
+ menchie, ok := menchieRaw.(map[string]any)
+ if !ok {
+ suite.FailNow("couldn't coerce menchie")
+ }
+
+ if _, ok := menchie["id"]; ok {
+ menchie["id"] = id.Highest
+ }
+ }
+ }
+
+ // Make fields of any poll determinate.
+ if pollRaw, ok := rawMap["poll"]; ok && pollRaw != nil {
+ poll, ok := pollRaw.(map[string]any)
+ if !ok {
+ suite.FailNow("couldn't coerce poll")
+ }
+
+ if _, ok := poll["id"]; ok {
+ poll["id"] = id.Highest
+ }
+
+ if _, ok := poll["expires_at"]; ok {
+ poll["expires_at"] = "ah like you know whatever dude it's chill"
+ }
+ }
+
+ // Replace account since that's not really
+ // what we care about for these tests.
+ if _, ok := rawMap["account"]; ok {
+ rawMap["account"] = "yeah this is my account, what about it punk"
+ }
+
+ // If status contains an embedded
+ // reblog do the same thing for that.
+ if reblogRaw, ok := rawMap["reblog"]; ok && reblogRaw != nil {
+ reblog, ok := reblogRaw.(map[string]any)
+ if !ok {
+ suite.FailNow("couldn't coerce reblog")
+ }
+ suite.determinateStatus(reblog)
+ }
+}
+
func (suite *StatusStandardTestSuite) SetupSuite() {
suite.testTokens = testrig.NewTestTokens()
suite.testClients = testrig.NewTestClients()
diff --git a/internal/api/client/statuses/statusboost_test.go b/internal/api/client/statuses/statusboost_test.go
index f6f589a5c..8642ba7aa 100644
--- a/internal/api/client/statuses/statusboost_test.go
+++ b/internal/api/client/statuses/statusboost_test.go
@@ -17,9 +17,6 @@
import (
"context"
- "encoding/json"
- "fmt"
- "io/ioutil"
"net/http"
"net/http/httptest"
"strings"
@@ -28,7 +25,7 @@
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/api/client/statuses"
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
+ apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/testrig"
@@ -38,212 +35,596 @@ type StatusBoostTestSuite struct {
StatusStandardTestSuite
}
-func (suite *StatusBoostTestSuite) TestPostBoost() {
- t := suite.testTokens["local_account_1"]
- oauthToken := oauth.DBTokenToToken(t)
-
- targetStatus := suite.testStatuses["admin_account_status_1"]
-
- // setup
+func (suite *StatusBoostTestSuite) postStatusBoost(
+ targetStatusID string,
+ app *gtsmodel.Application,
+ token *gtsmodel.Token,
+ user *gtsmodel.User,
+ account *gtsmodel.Account,
+) (string, *httptest.ResponseRecorder) {
recorder := httptest.NewRecorder()
ctx, _ := testrig.CreateGinTestContext(recorder, nil)
- ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
- ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
- ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_1"])
- ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"])
- ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", targetStatus.ID, 1)), nil) // the endpoint we're hitting
+ ctx.Set(oauth.SessionAuthorizedApplication, app)
+ ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(token))
+ ctx.Set(oauth.SessionAuthorizedUser, user)
+ ctx.Set(oauth.SessionAuthorizedAccount, account)
+
+ const pathBase = "http://localhost:8080/api" + statuses.ReblogPath
+ path := strings.ReplaceAll(pathBase, ":"+apiutil.IDKey, targetStatusID)
+ ctx.Request = httptest.NewRequest(http.MethodPost, path, nil)
ctx.Request.Header.Set("accept", "application/json")
- // normally the router would populate these params from the path values,
- // but because we're calling the function directly, we need to set them manually.
+ // Populate target status ID.
ctx.Params = gin.Params{
gin.Param{
- Key: statuses.IDKey,
- Value: targetStatus.ID,
+ Key: apiutil.IDKey,
+ Value: targetStatusID,
},
}
+ // Trigger handler.
suite.statusModule.StatusBoostPOSTHandler(ctx)
+ return suite.parseStatusResponse(recorder)
+}
- // check response
- suite.EqualValues(http.StatusOK, recorder.Code)
+func (suite *StatusBoostTestSuite) TestPostBoost() {
+ var (
+ targetStatus = suite.testStatuses["admin_account_status_1"]
+ app = suite.testApplications["application_1"]
+ token = suite.testTokens["local_account_1"]
+ user = suite.testUsers["local_account_1"]
+ account = suite.testAccounts["local_account_1"]
+ )
- result := recorder.Result()
- defer result.Body.Close()
- b, err := ioutil.ReadAll(result.Body)
- suite.NoError(err)
+ out, recorder := suite.postStatusBoost(
+ targetStatus.ID,
+ app,
+ token,
+ user,
+ account,
+ )
- statusReply := &apimodel.Status{}
- err = json.Unmarshal(b, statusReply)
- suite.NoError(err)
+ // We should have OK from
+ // our call to the function.
+ suite.Equal(http.StatusOK, recorder.Code)
- suite.False(statusReply.Sensitive)
- suite.Equal(apimodel.VisibilityPublic, statusReply.Visibility)
-
- suite.Empty(statusReply.SpoilerText)
- suite.Empty(statusReply.Content)
- suite.Equal("the_mighty_zork", statusReply.Account.Username)
- suite.Len(statusReply.MediaAttachments, 0)
- suite.Len(statusReply.Mentions, 0)
- suite.Len(statusReply.Emojis, 0)
- suite.Len(statusReply.Tags, 0)
-
- suite.NotNil(statusReply.Application)
- suite.Equal("really cool gts application", statusReply.Application.Name)
-
- suite.NotNil(statusReply.Reblog)
- suite.Equal(1, statusReply.Reblog.ReblogsCount)
- suite.Equal(1, statusReply.Reblog.FavouritesCount)
- suite.Equal(targetStatus.Content, statusReply.Reblog.Content)
- suite.Equal(targetStatus.ContentWarning, statusReply.Reblog.SpoilerText)
- suite.Equal(targetStatus.AccountID, statusReply.Reblog.Account.ID)
- suite.Len(statusReply.Reblog.MediaAttachments, 1)
- suite.Len(statusReply.Reblog.Tags, 1)
- suite.Len(statusReply.Reblog.Emojis, 1)
- suite.True(statusReply.Reblogged)
- suite.True(statusReply.Reblog.Reblogged)
- suite.Equal("superseriousbusiness", statusReply.Reblog.Application.Name)
+ // Target status should now
+ // be "reblogged" by us.
+ suite.Equal(`{
+ "account": "yeah this is my account, what about it punk",
+ "application": {
+ "name": "really cool gts application",
+ "website": "https://reallycool.app"
+ },
+ "bookmarked": true,
+ "card": null,
+ "content": "",
+ "created_at": "right the hell just now babyee",
+ "emojis": [],
+ "favourited": true,
+ "favourites_count": 0,
+ "id": "ZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ "in_reply_to_account_id": null,
+ "in_reply_to_id": null,
+ "interaction_policy": {
+ "can_favourite": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reblog": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reply": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ }
+ },
+ "language": null,
+ "media_attachments": [],
+ "mentions": [],
+ "muted": false,
+ "pinned": false,
+ "poll": null,
+ "reblog": {
+ "account": "yeah this is my account, what about it punk",
+ "application": {
+ "name": "superseriousbusiness",
+ "website": "https://superserious.business"
+ },
+ "bookmarked": true,
+ "card": null,
+ "content": "hello world! #welcome ! first post on the instance :rainbow: !",
+ "created_at": "right the hell just now babyee",
+ "emojis": [
+ {
+ "category": "reactions",
+ "shortcode": "rainbow",
+ "static_url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png",
+ "url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png",
+ "visible_in_picker": true
+ }
+ ],
+ "favourited": true,
+ "favourites_count": 1,
+ "id": "ZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ "in_reply_to_account_id": null,
+ "in_reply_to_id": null,
+ "interaction_policy": {
+ "can_favourite": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reblog": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reply": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ }
+ },
+ "language": "en",
+ "media_attachments": [
+ {
+ "blurhash": "LIIE|gRj00WB-;j[t7j[4nWBj[Rj",
+ "description": "Black and white image of some 50's style text saying: Welcome On Board",
+ "id": "01F8MH6NEM8D7527KZAECTCR76",
+ "meta": {
+ "focus": {
+ "x": 0,
+ "y": 0
+ },
+ "original": {
+ "aspect": 1.9047619,
+ "height": 630,
+ "size": "1200x630",
+ "width": 1200
+ },
+ "small": {
+ "aspect": 1.9104477,
+ "height": 268,
+ "size": "512x268",
+ "width": 512
+ }
+ },
+ "preview_remote_url": null,
+ "preview_url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.webp",
+ "remote_url": null,
+ "text_url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpg",
+ "type": "image",
+ "url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpg"
+ }
+ ],
+ "mentions": [],
+ "muted": false,
+ "pinned": false,
+ "poll": null,
+ "reblog": null,
+ "reblogged": true,
+ "reblogs_count": 1,
+ "replies_count": 1,
+ "sensitive": false,
+ "spoiler_text": "",
+ "tags": [
+ {
+ "name": "welcome",
+ "url": "http://localhost:8080/tags/welcome"
+ }
+ ],
+ "text": "hello world! #welcome ! first post on the instance :rainbow: !",
+ "uri": "http://localhost:8080/some/determinate/url",
+ "url": "http://localhost:8080/some/determinate/url",
+ "visibility": "public"
+ },
+ "reblogged": true,
+ "reblogs_count": 0,
+ "replies_count": 0,
+ "sensitive": false,
+ "spoiler_text": "",
+ "tags": [],
+ "uri": "http://localhost:8080/some/determinate/url",
+ "url": "http://localhost:8080/some/determinate/url",
+ "visibility": "public"
+}`, out)
}
func (suite *StatusBoostTestSuite) TestPostBoostOwnFollowersOnly() {
- t := suite.testTokens["local_account_1"]
- oauthToken := oauth.DBTokenToToken(t)
+ var (
+ targetStatus = suite.testStatuses["local_account_1_status_5"]
+ app = suite.testApplications["application_1"]
+ token = suite.testTokens["local_account_1"]
+ user = suite.testUsers["local_account_1"]
+ account = suite.testAccounts["local_account_1"]
+ )
- testStatus := suite.testStatuses["local_account_1_status_5"]
- testAccount := suite.testAccounts["local_account_1"]
- testUser := suite.testUsers["local_account_1"]
+ out, recorder := suite.postStatusBoost(
+ targetStatus.ID,
+ app,
+ token,
+ user,
+ account,
+ )
- recorder := httptest.NewRecorder()
- ctx, _ := testrig.CreateGinTestContext(recorder, nil)
- ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
- ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
- ctx.Set(oauth.SessionAuthorizedUser, testUser)
- ctx.Set(oauth.SessionAuthorizedAccount, testAccount)
- ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", testStatus.ID, 1)), nil)
- ctx.Request.Header.Set("accept", "application/json")
+ // We should have OK from
+ // our call to the function.
+ suite.Equal(http.StatusOK, recorder.Code)
- ctx.Params = gin.Params{
- gin.Param{
- Key: statuses.IDKey,
- Value: testStatus.ID,
- },
- }
-
- suite.statusModule.StatusBoostPOSTHandler(ctx)
-
- // check response
- suite.EqualValues(http.StatusOK, recorder.Code)
-
- result := recorder.Result()
- defer result.Body.Close()
- b, err := ioutil.ReadAll(result.Body)
- suite.NoError(err)
-
- responseStatus := &apimodel.Status{}
- err = json.Unmarshal(b, responseStatus)
- suite.NoError(err)
-
- suite.False(responseStatus.Sensitive)
- suite.Equal(suite.tc.VisToAPIVis(context.Background(), testStatus.Visibility), responseStatus.Visibility)
-
- suite.Empty(responseStatus.SpoilerText)
- suite.Empty(responseStatus.Content)
- suite.Equal("the_mighty_zork", responseStatus.Account.Username)
- suite.Len(responseStatus.MediaAttachments, 0)
- suite.Len(responseStatus.Mentions, 0)
- suite.Len(responseStatus.Emojis, 0)
- suite.Len(responseStatus.Tags, 0)
-
- suite.NotNil(responseStatus.Application)
- suite.Equal("really cool gts application", responseStatus.Application.Name)
-
- suite.NotNil(responseStatus.Reblog)
- suite.Equal(1, responseStatus.Reblog.ReblogsCount)
- suite.Equal(0, responseStatus.Reblog.FavouritesCount)
- suite.Equal(testStatus.Content, responseStatus.Reblog.Content)
- suite.Equal(testStatus.ContentWarning, responseStatus.Reblog.SpoilerText)
- suite.Equal(testStatus.AccountID, responseStatus.Reblog.Account.ID)
- suite.Equal(suite.tc.VisToAPIVis(context.Background(), testStatus.Visibility), responseStatus.Reblog.Visibility)
- suite.Empty(responseStatus.Reblog.MediaAttachments)
- suite.Empty(responseStatus.Reblog.Tags)
- suite.Empty(responseStatus.Reblog.Emojis)
- suite.True(responseStatus.Reblogged)
- suite.True(responseStatus.Reblog.Reblogged)
- suite.Equal("really cool gts application", responseStatus.Reblog.Application.Name)
+ // Target status should now
+ // be "reblogged" by us.
+ suite.Equal(`{
+ "account": "yeah this is my account, what about it punk",
+ "application": {
+ "name": "really cool gts application",
+ "website": "https://reallycool.app"
+ },
+ "bookmarked": false,
+ "card": null,
+ "content": "",
+ "created_at": "right the hell just now babyee",
+ "emojis": [],
+ "favourited": false,
+ "favourites_count": 0,
+ "id": "ZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ "in_reply_to_account_id": null,
+ "in_reply_to_id": null,
+ "interaction_policy": {
+ "can_favourite": {
+ "always": [
+ "author",
+ "followers",
+ "mentioned",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reblog": {
+ "always": [
+ "author",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reply": {
+ "always": [
+ "author",
+ "followers",
+ "mentioned",
+ "me"
+ ],
+ "with_approval": []
+ }
+ },
+ "language": null,
+ "media_attachments": [],
+ "mentions": [],
+ "muted": false,
+ "pinned": false,
+ "poll": null,
+ "reblog": {
+ "account": "yeah this is my account, what about it punk",
+ "application": {
+ "name": "really cool gts application",
+ "website": "https://reallycool.app"
+ },
+ "bookmarked": false,
+ "card": null,
+ "content": "hi!",
+ "created_at": "right the hell just now babyee",
+ "emojis": [],
+ "favourited": false,
+ "favourites_count": 0,
+ "id": "ZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ "in_reply_to_account_id": null,
+ "in_reply_to_id": null,
+ "interaction_policy": {
+ "can_favourite": {
+ "always": [
+ "author",
+ "followers",
+ "mentioned",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reblog": {
+ "always": [
+ "author",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reply": {
+ "always": [
+ "author",
+ "followers",
+ "mentioned",
+ "me"
+ ],
+ "with_approval": []
+ }
+ },
+ "language": "en",
+ "media_attachments": [],
+ "mentions": [],
+ "muted": false,
+ "pinned": false,
+ "poll": null,
+ "reblog": null,
+ "reblogged": true,
+ "reblogs_count": 1,
+ "replies_count": 0,
+ "sensitive": false,
+ "spoiler_text": "",
+ "tags": [],
+ "text": "hi!",
+ "uri": "http://localhost:8080/some/determinate/url",
+ "url": "http://localhost:8080/some/determinate/url",
+ "visibility": "private"
+ },
+ "reblogged": true,
+ "reblogs_count": 0,
+ "replies_count": 0,
+ "sensitive": false,
+ "spoiler_text": "",
+ "tags": [],
+ "uri": "http://localhost:8080/some/determinate/url",
+ "url": "http://localhost:8080/some/determinate/url",
+ "visibility": "private"
+}`, out)
}
-// try to boost a status that's not boostable / visible to us
+// Try to boost a status that's
+// not boostable / visible to us.
func (suite *StatusBoostTestSuite) TestPostUnboostable() {
- t := suite.testTokens["local_account_1"]
- oauthToken := oauth.DBTokenToToken(t)
+ var (
+ targetStatus = suite.testStatuses["local_account_2_status_4"]
+ app = suite.testApplications["application_1"]
+ token = suite.testTokens["local_account_1"]
+ user = suite.testUsers["local_account_1"]
+ account = suite.testAccounts["local_account_1"]
+ )
- targetStatus := suite.testStatuses["local_account_2_status_4"]
+ out, recorder := suite.postStatusBoost(
+ targetStatus.ID,
+ app,
+ token,
+ user,
+ account,
+ )
- // setup
- recorder := httptest.NewRecorder()
- ctx, _ := testrig.CreateGinTestContext(recorder, nil)
- ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
- ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
- ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_1"])
- ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"])
- ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", targetStatus.ID, 1)), nil) // the endpoint we're hitting
- ctx.Request.Header.Set("accept", "application/json")
-
- // normally the router would populate these params from the path values,
- // but because we're calling the function directly, we need to set them manually.
- ctx.Params = gin.Params{
- gin.Param{
- Key: statuses.IDKey,
- Value: targetStatus.ID,
- },
- }
-
- suite.statusModule.StatusBoostPOSTHandler(ctx)
-
- // check response
+ // We should have 403 from
+ // our call to the function.
suite.Equal(http.StatusForbidden, recorder.Code)
- result := recorder.Result()
- defer result.Body.Close()
- b, err := ioutil.ReadAll(result.Body)
- suite.NoError(err)
- suite.Equal(`{"error":"Forbidden: you do not have permission to boost this status"}`, string(b))
+ // We should have a helpful message.
+ suite.Equal(`{
+ "error": "Forbidden: you do not have permission to boost this status"
+}`, out)
}
-// try to boost a status that's not visible to the user
+// Try to boost a status that's not visible to the user.
func (suite *StatusBoostTestSuite) TestPostNotVisible() {
- // stop local_account_2 following zork
- err := suite.db.DeleteByID(context.Background(), suite.testFollows["local_account_2_local_account_1"].ID, >smodel.Follow{})
- suite.NoError(err)
-
- t := suite.testTokens["local_account_2"]
- oauthToken := oauth.DBTokenToToken(t)
-
- targetStatus := suite.testStatuses["local_account_1_status_3"] // this is a mutual only status and these accounts aren't mutuals
-
- // setup
- recorder := httptest.NewRecorder()
- ctx, _ := testrig.CreateGinTestContext(recorder, nil)
- ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
- ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
- ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_2"])
- ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_2"])
- ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", targetStatus.ID, 1)), nil) // the endpoint we're hitting
- ctx.Request.Header.Set("accept", "application/json")
-
- // normally the router would populate these params from the path values,
- // but because we're calling the function directly, we need to set them manually.
- ctx.Params = gin.Params{
- gin.Param{
- Key: statuses.IDKey,
- Value: targetStatus.ID,
- },
+ // Stop local_account_2 following zork.
+ err := suite.db.DeleteFollowByID(
+ context.Background(),
+ suite.testFollows["local_account_2_local_account_1"].ID,
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
}
- suite.statusModule.StatusBoostPOSTHandler(ctx)
+ var (
+ // This is a mutual only status and
+ // these accounts aren't mutuals anymore.
+ targetStatus = suite.testStatuses["local_account_1_status_3"]
+ app = suite.testApplications["application_1"]
+ token = suite.testTokens["local_account_2"]
+ user = suite.testUsers["local_account_2"]
+ account = suite.testAccounts["local_account_2"]
+ )
- // check response
- suite.Equal(http.StatusNotFound, recorder.Code) // we 404 statuses that aren't visible
+ out, recorder := suite.postStatusBoost(
+ targetStatus.ID,
+ app,
+ token,
+ user,
+ account,
+ )
+
+ // We should have 404 from
+ // our call to the function.
+ suite.Equal(http.StatusNotFound, recorder.Code)
+
+ // We should have a helpful message.
+ suite.Equal(`{
+ "error": "Not Found: target status not found"
+}`, out)
+}
+
+// Boost a status that's pending approval by us.
+func (suite *StatusBoostTestSuite) TestPostBoostImplicitAccept() {
+ var (
+ targetStatus = suite.testStatuses["admin_account_status_5"]
+ app = suite.testApplications["application_1"]
+ token = suite.testTokens["local_account_2"]
+ user = suite.testUsers["local_account_2"]
+ account = suite.testAccounts["local_account_2"]
+ )
+
+ out, recorder := suite.postStatusBoost(
+ targetStatus.ID,
+ app,
+ token,
+ user,
+ account,
+ )
+
+ // We should have OK from
+ // our call to the function.
+ suite.Equal(http.StatusOK, recorder.Code)
+
+ // Target status should now
+ // be "reblogged" by us.
+ suite.Equal(`{
+ "account": "yeah this is my account, what about it punk",
+ "application": {
+ "name": "really cool gts application",
+ "website": "https://reallycool.app"
+ },
+ "bookmarked": false,
+ "card": null,
+ "content": "",
+ "created_at": "right the hell just now babyee",
+ "emojis": [],
+ "favourited": false,
+ "favourites_count": 0,
+ "id": "ZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ "in_reply_to_account_id": null,
+ "in_reply_to_id": null,
+ "interaction_policy": {
+ "can_favourite": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reblog": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ },
+ "can_reply": {
+ "always": [
+ "public",
+ "me"
+ ],
+ "with_approval": []
+ }
+ },
+ "language": null,
+ "media_attachments": [],
+ "mentions": [],
+ "muted": false,
+ "pinned": false,
+ "poll": null,
+ "reblog": {
+ "account": "yeah this is my account, what about it punk",
+ "application": {
+ "name": "superseriousbusiness",
+ "website": "https://superserious.business"
+ },
+ "bookmarked": false,
+ "card": null,
+ "content": "
âšī¸ Note from ` + host + `: `)
+ note.WriteString(`This reply is pending your approval. You can quickly accept it by liking, boosting or replying to it. You can also accept or reject it at the following link: `)
+ note.WriteString(``)
+ note.WriteString(settingsURL)
+ note.WriteString(`.`)
+ note.WriteString(`
`)
+
+ return text.SanitizeToHTML(note.String()), nil
+}
+
// ContentToContentLanguage tries to
// extract a content string and language
// tag string from the given intermediary
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
index 8a4f49a4c..519db348a 100644
--- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
+++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
@@ -844,9 +844,7 @@ func (h *histogram) Write(out *dto.Metric) error {
}}
}
- // If exemplars are not configured, the cap will be 0.
- // So append is not needed in this case.
- if cap(h.nativeExemplars.exemplars) > 0 {
+ if h.nativeExemplars.isEnabled() {
h.nativeExemplars.Lock()
his.Exemplars = append(his.Exemplars, h.nativeExemplars.exemplars...)
h.nativeExemplars.Unlock()
@@ -1665,6 +1663,10 @@ type nativeExemplars struct {
exemplars []*dto.Exemplar
}
+func (n *nativeExemplars) isEnabled() bool {
+ return n.ttl != -1
+}
+
func makeNativeExemplars(ttl time.Duration, maxCount int) nativeExemplars {
if ttl == 0 {
ttl = 5 * time.Minute
@@ -1686,7 +1688,7 @@ func makeNativeExemplars(ttl time.Duration, maxCount int) nativeExemplars {
}
func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
- if n.ttl == -1 {
+ if !n.isEnabled() {
return
}
diff --git a/vendor/go.opentelemetry.io/otel/.golangci.yml b/vendor/go.opentelemetry.io/otel/.golangci.yml
index a5f904197..d9abe194d 100644
--- a/vendor/go.opentelemetry.io/otel/.golangci.yml
+++ b/vendor/go.opentelemetry.io/otel/.golangci.yml
@@ -64,12 +64,12 @@ issues:
- path: _test\.go
linters:
- gosec
- # Ignoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
+ # Igonoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
# as we commonly use it in tests and examples.
- text: "G404:"
linters:
- gosec
- # Ignoring gosec G402: TLS MinVersion too low
+ # Igonoring gosec G402: TLS MinVersion too low
# as the https://pkg.go.dev/crypto/tls#Config handles MinVersion default well.
- text: "G402: TLS MinVersion too low."
linters:
diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md
index fb107426e..6107c17b8 100644
--- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md
+++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md
@@ -11,25 +11,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
-## [1.30.0/0.52.0/0.6.0/0.0.9] 2024-09-09
-
-### Added
-
-- Support `OTEL_EXPORTER_OTLP_LOGS_INSECURE` and `OTEL_EXPORTER_OTLP_INSECURE` environments in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#5739)
-- The `WithResource` option for `NewMeterProvider` now merges the provided resources with the ones from environment variables. (#5773)
-- The `WithResource` option for `NewLoggerProvider` now merges the provided resources with the ones from environment variables. (#5773)
-- Add UTF-8 support to `go.opentelemetry.io/otel/exporters/prometheus`. (#5755)
-
-### Fixed
-
-- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754)
-- Fix panic on instruments creation when setting meter provider. (#5758)
-- Fix an issue where `SetMeterProvider` in `go.opentelemetry.io/otel` might miss the delegation for instruments and registries. (#5780)
-
-### Removed
-
-- Drop support for [Go 1.21]. (#5736, #5740, #5800)
-
## [1.29.0/0.51.0/0.5.0] 2024-08-23
This release is the last to support [Go 1.21].
@@ -1914,7 +1895,7 @@ with major version 0.
- Setting error status while recording error with Span from oteltest package. (#1729)
- The concept of a remote and local Span stored in a context is unified to just the current Span.
Because of this `"go.opentelemetry.io/otel/trace".RemoteSpanContextFromContext` is removed as it is no longer needed.
- Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContext` can be used to return the current Span.
+ Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContex` can be used to return the current Span.
If needed, that Span's `SpanContext.IsRemote()` can then be used to determine if it is remote or not. (#1731)
- The `HasRemoteParent` field of the `"go.opentelemetry.io/otel/sdk/trace".SamplingParameters` is removed.
This field is redundant to the information returned from the `Remote` method of the `SpanContext` held in the `ParentContext` field. (#1749)
@@ -2488,7 +2469,7 @@ This release migrates the default OpenTelemetry SDK into its own Go module, deco
- Prometheus exporter will not apply stale updates or forget inactive metrics. (#903)
- Add test for api.standard `HTTPClientAttributesFromHTTPRequest`. (#905)
- Bump github.com/golangci/golangci-lint from 1.27.0 to 1.28.1 in /tools. (#901, #913)
-- Update otel-collector example to use the v0.5.0 collector. (#915)
+- Update otel-colector example to use the v0.5.0 collector. (#915)
- The `grpctrace` instrumentation uses a span name conforming to the OpenTelemetry semantic conventions (does not contain a leading slash (`/`)). (#922)
- The `grpctrace` instrumentation includes an `rpc.method` attribute now set to the gRPC method name. (#900, #922)
- The `grpctrace` instrumentation `rpc.service` attribute now contains the package name if one exists.
@@ -3081,8 +3062,7 @@ 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.30.0...HEAD
-[1.30.0/0.52.0/0.6.0/0.0.9]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.30.0
+[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.29.0...HEAD
[1.29.0/0.51.0/0.5.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.29.0
[1.28.0/0.50.0/0.4.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.28.0
[1.27.0/0.49.0/0.3.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.27.0
diff --git a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
index 915807253..b7402576f 100644
--- a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
+++ b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
@@ -578,10 +578,7 @@ See also:
The tests should never leak goroutines.
Use the term `ConcurrentSafe` in the test name when it aims to verify the
-absence of race conditions. The top-level tests with this term will be run
-many times in the `test-concurrent-safe` CI job to increase the chance of
-catching concurrency issues. This does not apply to subtests when this term
-is not in their root name.
+absence of race conditions.
### Internal packages
diff --git a/vendor/go.opentelemetry.io/otel/Makefile b/vendor/go.opentelemetry.io/otel/Makefile
index b04695b24..070b1e57d 100644
--- a/vendor/go.opentelemetry.io/otel/Makefile
+++ b/vendor/go.opentelemetry.io/otel/Makefile
@@ -145,14 +145,12 @@ build-tests/%:
# Tests
-TEST_TARGETS := test-default test-bench test-short test-verbose test-race test-concurrent-safe
+TEST_TARGETS := test-default test-bench test-short test-verbose test-race
.PHONY: $(TEST_TARGETS) test
test-default test-race: ARGS=-race
test-bench: ARGS=-run=xxxxxMatchNothingxxxxx -test.benchtime=1ms -bench=.
test-short: ARGS=-short
test-verbose: ARGS=-v -race
-test-concurrent-safe: ARGS=-run=ConcurrentSafe -count=100 -race
-test-concurrent-safe: TIMEOUT=120
$(TEST_TARGETS): test
test: $(OTEL_GO_MOD_DIRS:%=test/%)
test/%: DIR=$*
diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md
index 9a6570703..657df3471 100644
--- a/vendor/go.opentelemetry.io/otel/README.md
+++ b/vendor/go.opentelemetry.io/otel/README.md
@@ -51,18 +51,25 @@ Currently, this project supports the following environments.
|----------|------------|--------------|
| Ubuntu | 1.23 | amd64 |
| Ubuntu | 1.22 | amd64 |
+| Ubuntu | 1.21 | amd64 |
| Ubuntu | 1.23 | 386 |
| Ubuntu | 1.22 | 386 |
+| Ubuntu | 1.21 | 386 |
| Linux | 1.23 | arm64 |
| Linux | 1.22 | arm64 |
+| Linux | 1.21 | arm64 |
| macOS 13 | 1.23 | amd64 |
| macOS 13 | 1.22 | amd64 |
+| macOS 13 | 1.21 | amd64 |
| macOS | 1.23 | arm64 |
| macOS | 1.22 | arm64 |
+| macOS | 1.21 | arm64 |
| Windows | 1.23 | amd64 |
| Windows | 1.22 | amd64 |
+| Windows | 1.21 | amd64 |
| Windows | 1.23 | 386 |
| Windows | 1.22 | 386 |
+| Windows | 1.21 | 386 |
While this project should work for other systems, no compatibility guarantees
are made for those systems currently.
diff --git a/vendor/go.opentelemetry.io/otel/baggage/baggage.go b/vendor/go.opentelemetry.io/otel/baggage/baggage.go
index 36f536703..b3569e95e 100644
--- a/vendor/go.opentelemetry.io/otel/baggage/baggage.go
+++ b/vendor/go.opentelemetry.io/otel/baggage/baggage.go
@@ -50,7 +50,7 @@ type Property struct {
// component boundaries may impose their own restrictions on Property key.
// For example, the W3C Baggage specification restricts the Property keys to strings that
// satisfy the token definition from RFC7230, Section 3.2.6.
-// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key.
+// For maximum compatibility, alpha-numeric value are strongly recommended to be used as Property key.
func NewKeyProperty(key string) (Property, error) {
if !validateBaggageName(key) {
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key)
@@ -90,7 +90,7 @@ func NewKeyValueProperty(key, value string) (Property, error) {
// component boundaries may impose their own restrictions on Property key.
// For example, the W3C Baggage specification restricts the Property keys to strings that
// satisfy the token definition from RFC7230, Section 3.2.6.
-// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key.
+// For maximum compatibility, alpha-numeric value are strongly recommended to be used as Property key.
func NewKeyValuePropertyRaw(key, value string) (Property, error) {
if !validateBaggageName(key) {
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key)
@@ -287,7 +287,7 @@ func NewMember(key, value string, props ...Property) (Member, error) {
// component boundaries may impose their own restrictions on baggage key.
// For example, the W3C Baggage specification restricts the baggage keys to strings that
// satisfy the token definition from RFC7230, Section 3.2.6.
-// For maximum compatibility, alphanumeric value are strongly recommended to be used as baggage key.
+// For maximum compatibility, alpha-numeric value are strongly recommended to be used as baggage key.
func NewMemberRaw(key, value string, props ...Property) (Member, error) {
m := Member{
key: key,
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go
index 8d4b4bf08..8f84a7996 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go
@@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
if cfg.ServiceConfig != "" {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
}
- // Prioritize GRPCCredentials over Insecure (passing both is an error).
+ // Priroritize GRPCCredentials over Insecure (passing both is an error).
if cfg.Traces.GRPCCredentials != nil {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))
} else if cfg.Traces.Insecure {
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go
index 9fea75ad1..43534cbfb 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go
@@ -22,7 +22,7 @@
The value must contain a scheme ("http" or "https") and host.
The value may additionally contain a port and a path.
The value should not contain a query string or fragment.
-The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithURLPath] options.
+The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WitnInsecure], and [WithURLPath] options.
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS (default: none) -
key-value pairs used as headers associated with HTTP requests.
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go
index 4cfd6c27f..2ebbc752f 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go
@@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
if cfg.ServiceConfig != "" {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
}
- // Prioritize GRPCCredentials over Insecure (passing both is an error).
+ // Priroritize GRPCCredentials over Insecure (passing both is an error).
if cfg.Traces.GRPCCredentials != nil {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))
} else if cfg.Traces.Insecure {
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go
index ab473f01f..780992528 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go
@@ -5,5 +5,5 @@
// Version is the current release version of the OpenTelemetry OTLP trace exporter in use.
func Version() string {
- return "1.30.0"
+ return "1.29.0"
}
diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go b/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go
index 660675dd6..a10ab7f1d 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go
@@ -7,7 +7,6 @@
"strings"
"github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/common/model"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/metric"
@@ -132,10 +131,7 @@ func WithoutScopeInfo() Option {
// have special behavior based on their name.
func WithNamespace(ns string) Option {
return optionFunc(func(cfg config) config {
- if model.NameValidationScheme != model.UTF8Validation {
- // Only sanitize if prometheus does not support UTF-8.
- ns = model.EscapeName(ns, model.NameEscapingScheme)
- }
+ ns = sanitizeName(ns)
if !strings.HasSuffix(ns, "_") {
// namespace and metric names should be separated with an underscore,
// adds a trailing underscore if there is not one already.
diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go b/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go
index b0f5f3730..d2e387e60 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go
@@ -11,10 +11,11 @@
"slices"
"strings"
"sync"
+ "unicode"
+ "unicode/utf8"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
- "github.com/prometheus/common/model"
"google.golang.org/protobuf/proto"
"go.opentelemetry.io/otel"
@@ -297,38 +298,28 @@ func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metric
}
// getAttrs parses the attribute.Set to two lists of matching Prometheus-style
-// keys and values.
+// keys and values. It sanitizes invalid characters and handles duplicate keys
+// (due to sanitization) by sorting and concatenating the values following the spec.
func getAttrs(attrs attribute.Set, ks, vs [2]string, resourceKV keyVals) ([]string, []string) {
+ keysMap := make(map[string][]string)
+ itr := attrs.Iter()
+ for itr.Next() {
+ kv := itr.Attribute()
+ key := strings.Map(sanitizeRune, string(kv.Key))
+ if _, ok := keysMap[key]; !ok {
+ keysMap[key] = []string{kv.Value.Emit()}
+ } else {
+ // if the sanitized key is a duplicate, append to the list of keys
+ keysMap[key] = append(keysMap[key], kv.Value.Emit())
+ }
+ }
+
keys := make([]string, 0, attrs.Len())
values := make([]string, 0, attrs.Len())
- itr := attrs.Iter()
-
- if model.NameValidationScheme == model.UTF8Validation {
- // Do not perform sanitization if prometheus supports UTF-8.
- for itr.Next() {
- kv := itr.Attribute()
- keys = append(keys, string(kv.Key))
- values = append(values, kv.Value.Emit())
- }
- } else {
- // It sanitizes invalid characters and handles duplicate keys
- // (due to sanitization) by sorting and concatenating the values following the spec.
- keysMap := make(map[string][]string)
- for itr.Next() {
- kv := itr.Attribute()
- key := model.EscapeName(string(kv.Key), model.NameEscapingScheme)
- if _, ok := keysMap[key]; !ok {
- keysMap[key] = []string{kv.Value.Emit()}
- } else {
- // if the sanitized key is a duplicate, append to the list of keys
- keysMap[key] = append(keysMap[key], kv.Value.Emit())
- }
- }
- for key, vals := range keysMap {
- keys = append(keys, key)
- slices.Sort(vals)
- values = append(values, strings.Join(vals, ";"))
- }
+ for key, vals := range keysMap {
+ keys = append(keys, key)
+ slices.Sort(vals)
+ values = append(values, strings.Join(vals, ";"))
}
if ks[0] != "" {
@@ -356,6 +347,13 @@ func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, erro
return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), scope.Name, scope.Version)
}
+func sanitizeRune(r rune) rune {
+ if unicode.IsLetter(r) || unicode.IsDigit(r) || r == ':' || r == '_' {
+ return r
+ }
+ return '_'
+}
+
var unitSuffixes = map[string]string{
// Time
"d": "_days",
@@ -394,11 +392,7 @@ func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, erro
// getName returns the sanitized name, prefixed with the namespace and suffixed with unit.
func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
- name := m.Name
- if model.NameValidationScheme != model.UTF8Validation {
- // Only sanitize if prometheus does not support UTF-8.
- name = model.EscapeName(name, model.NameEscapingScheme)
- }
+ name := sanitizeName(m.Name)
addCounterSuffix := !c.withoutCounterSuffixes && *typ == dto.MetricType_COUNTER
if addCounterSuffix {
// Remove the _total suffix here, as we will re-add the total suffix
@@ -417,6 +411,59 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
return name
}
+func sanitizeName(n string) string {
+ // This algorithm is based on strings.Map from Go 1.19.
+ const replacement = '_'
+
+ valid := func(i int, r rune) bool {
+ // Taken from
+ // https://github.com/prometheus/common/blob/dfbc25bd00225c70aca0d94c3c4bb7744f28ace0/model/metric.go#L92-L102
+ if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || r == '_' || r == ':' || (r >= '0' && r <= '9' && i > 0) {
+ return true
+ }
+ return false
+ }
+
+ // This output buffer b is initialized on demand, the first time a
+ // character needs to be replaced.
+ var b strings.Builder
+ for i, c := range n {
+ if valid(i, c) {
+ continue
+ }
+
+ if i == 0 && c >= '0' && c <= '9' {
+ // Prefix leading number with replacement character.
+ b.Grow(len(n) + 1)
+ _ = b.WriteByte(byte(replacement))
+ break
+ }
+ b.Grow(len(n))
+ _, _ = b.WriteString(n[:i])
+ _ = b.WriteByte(byte(replacement))
+ width := utf8.RuneLen(c)
+ n = n[i+width:]
+ break
+ }
+
+ // Fast path for unchanged input.
+ if b.Cap() == 0 { // b.Grow was not called above.
+ return n
+ }
+
+ for _, c := range n {
+ // Due to inlining, it is more performant to invoke WriteByte rather then
+ // WriteRune.
+ if valid(1, c) { // We are guaranteed to not be at the start.
+ _ = b.WriteByte(byte(c))
+ } else {
+ _ = b.WriteByte(byte(replacement))
+ }
+ }
+
+ return b.String()
+}
+
func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType {
switch v := m.Data.(type) {
case metricdata.Histogram[int64], metricdata.Histogram[float64]:
diff --git a/vendor/go.opentelemetry.io/otel/internal/global/meter.go b/vendor/go.opentelemetry.io/otel/internal/global/meter.go
index f2fc3929b..cfd1df9bf 100644
--- a/vendor/go.opentelemetry.io/otel/internal/global/meter.go
+++ b/vendor/go.opentelemetry.io/otel/internal/global/meter.go
@@ -5,8 +5,8 @@
import (
"container/list"
- "reflect"
"sync"
+ "sync/atomic"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
@@ -76,7 +76,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me
return val
}
- t := &meter{name: name, opts: opts, instruments: make(map[instID]delegatedInstrument)}
+ t := &meter{name: name, opts: opts}
p.meters[key] = t
return t
}
@@ -92,29 +92,17 @@ type meter struct {
opts []metric.MeterOption
mtx sync.Mutex
- instruments map[instID]delegatedInstrument
+ instruments []delegatedInstrument
registry list.List
- delegate metric.Meter
+ delegate atomic.Value // metric.Meter
}
type delegatedInstrument interface {
setDelegate(metric.Meter)
}
-// instID are the identifying properties of a instrument.
-type instID struct {
- // name is the name of the stream.
- name string
- // description is the description of the stream.
- description string
- // kind defines the functional group of the instrument.
- kind reflect.Type
- // unit is the unit of the stream.
- unit string
-}
-
// setDelegate configures m to delegate all Meter functionality to Meters
// created by provider.
//
@@ -122,12 +110,12 @@ type instID struct {
//
// It is guaranteed by the caller that this happens only once.
func (m *meter) setDelegate(provider metric.MeterProvider) {
+ meter := provider.Meter(m.name, m.opts...)
+ m.delegate.Store(meter)
+
m.mtx.Lock()
defer m.mtx.Unlock()
- meter := provider.Meter(m.name, m.opts...)
- m.delegate = meter
-
for _, inst := range m.instruments {
inst.setDelegate(meter)
}
@@ -145,295 +133,169 @@ func (m *meter) setDelegate(provider metric.MeterProvider) {
}
func (m *meter) Int64Counter(name string, options ...metric.Int64CounterOption) (metric.Int64Counter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64Counter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64Counter(name, options...)
- }
-
i := &siCounter{name: name, opts: options}
- cfg := metric.NewInt64CounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64UpDownCounter(name string, options ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64UpDownCounter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64UpDownCounter(name, options...)
- }
-
i := &siUpDownCounter{name: name, opts: options}
- cfg := metric.NewInt64UpDownCounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOption) (metric.Int64Histogram, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64Histogram(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64Histogram(name, options...)
- }
-
i := &siHistogram{name: name, opts: options}
- cfg := metric.NewInt64HistogramConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64Gauge(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64Gauge(name, options...)
- }
-
i := &siGauge{name: name, opts: options}
- cfg := metric.NewInt64GaugeConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64ObservableCounter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64ObservableCounter(name, options...)
- }
-
i := &aiCounter{name: name, opts: options}
- cfg := metric.NewInt64ObservableCounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64ObservableUpDownCounter(name string, options ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64ObservableUpDownCounter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64ObservableUpDownCounter(name, options...)
- }
-
i := &aiUpDownCounter{name: name, opts: options}
- cfg := metric.NewInt64ObservableUpDownCounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Int64ObservableGauge(name string, options ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Int64ObservableGauge(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Int64ObservableGauge(name, options...)
- }
-
i := &aiGauge{name: name, opts: options}
- cfg := metric.NewInt64ObservableGaugeConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64Counter(name string, options ...metric.Float64CounterOption) (metric.Float64Counter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64Counter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64Counter(name, options...)
- }
-
i := &sfCounter{name: name, opts: options}
- cfg := metric.NewFloat64CounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64UpDownCounter(name string, options ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64UpDownCounter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64UpDownCounter(name, options...)
- }
-
i := &sfUpDownCounter{name: name, opts: options}
- cfg := metric.NewFloat64UpDownCounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64Histogram(name string, options ...metric.Float64HistogramOption) (metric.Float64Histogram, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64Histogram(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64Histogram(name, options...)
- }
-
i := &sfHistogram{name: name, opts: options}
- cfg := metric.NewFloat64HistogramConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64Gauge(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64Gauge(name, options...)
- }
-
i := &sfGauge{name: name, opts: options}
- cfg := metric.NewFloat64GaugeConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64ObservableCounter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64ObservableCounter(name, options...)
- }
-
i := &afCounter{name: name, opts: options}
- cfg := metric.NewFloat64ObservableCounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64ObservableUpDownCounter(name string, options ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64ObservableUpDownCounter(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64ObservableUpDownCounter(name, options...)
- }
-
i := &afUpDownCounter{name: name, opts: options}
- cfg := metric.NewFloat64ObservableUpDownCounterConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
func (m *meter) Float64ObservableGauge(name string, options ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ return del.Float64ObservableGauge(name, options...)
+ }
m.mtx.Lock()
defer m.mtx.Unlock()
-
- if m.delegate != nil {
- return m.delegate.Float64ObservableGauge(name, options...)
- }
-
i := &afGauge{name: name, opts: options}
- cfg := metric.NewFloat64ObservableGaugeConfig(options...)
- id := instID{
- name: name,
- kind: reflect.TypeOf(i),
- description: cfg.Description(),
- unit: cfg.Unit(),
- }
- m.instruments[id] = i
+ m.instruments = append(m.instruments, i)
return i, nil
}
// RegisterCallback captures the function that will be called during Collect.
func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) (metric.Registration, error) {
+ if del, ok := m.delegate.Load().(metric.Meter); ok {
+ insts = unwrapInstruments(insts)
+ return del.RegisterCallback(f, insts...)
+ }
+
m.mtx.Lock()
defer m.mtx.Unlock()
- if m.delegate != nil {
- insts = unwrapInstruments(insts)
- return m.delegate.RegisterCallback(f, insts...)
- }
-
reg := ®istration{instruments: insts, function: f}
e := m.registry.PushBack(reg)
reg.unreg = func() error {
diff --git a/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go b/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go
index f8435d8f2..cf23db778 100644
--- a/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go
+++ b/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go
@@ -213,7 +213,7 @@ type Float64Observer interface {
}
// Float64Callback is a function registered with a Meter that makes
-// observations for a Float64Observable instrument it is registered with.
+// observations for a Float64Observerable instrument it is registered with.
// Calls to the Float64Observer record measurement values for the
// Float64Observable.
//
diff --git a/vendor/go.opentelemetry.io/otel/metric/asyncint64.go b/vendor/go.opentelemetry.io/otel/metric/asyncint64.go
index e079aaef1..c82ba5324 100644
--- a/vendor/go.opentelemetry.io/otel/metric/asyncint64.go
+++ b/vendor/go.opentelemetry.io/otel/metric/asyncint64.go
@@ -212,7 +212,7 @@ type Int64Observer interface {
}
// Int64Callback is a function registered with a Meter that makes observations
-// for an Int64Observable instrument it is registered with. Calls to the
+// for an Int64Observerable instrument it is registered with. Calls to the
// Int64Observer record measurement values for the Int64Observable.
//
// The function needs to complete in a finite amount of time and the deadline
diff --git a/vendor/go.opentelemetry.io/otel/renovate.json b/vendor/go.opentelemetry.io/otel/renovate.json
index 4d36b98cf..8c5ac55ca 100644
--- a/vendor/go.opentelemetry.io/otel/renovate.json
+++ b/vendor/go.opentelemetry.io/otel/renovate.json
@@ -19,10 +19,6 @@
"matchManagers": ["gomod"],
"matchDepTypes": ["indirect"],
"enabled": false
- },
- {
- "matchPackageNames": ["google.golang.org/genproto/googleapis/**"],
- "groupName": "googleapis"
}
]
}
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/config.go b/vendor/go.opentelemetry.io/otel/sdk/metric/config.go
index 544275a11..bbe7bf671 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/config.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/config.go
@@ -8,7 +8,6 @@
"fmt"
"sync"
- "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/resource"
)
@@ -104,11 +103,7 @@ func (o optionFunc) apply(conf config) config {
// go.opentelemetry.io/otel/sdk/resource package will be used.
func WithResource(res *resource.Resource) Option {
return optionFunc(func(conf config) config {
- var err error
- conf.res, err = resource.Merge(resource.Environment(), res)
- if err != nil {
- otel.Handle(err)
- }
+ conf.res = res
return conf
})
}
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go b/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go
index 2e6ac5434..b52a330b3 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go
@@ -234,8 +234,8 @@ func (i *float64Inst) aggregate(ctx context.Context, val float64, s attribute.Se
}
}
-// observableID is a comparable unique identifier of an observable.
-type observableID[N int64 | float64] struct {
+// observablID is a comparable unique identifier of an observable.
+type observablID[N int64 | float64] struct {
name string
description string
kind InstrumentKind
@@ -287,7 +287,7 @@ func newInt64Observable(m *meter, kind InstrumentKind, name, desc, u string) int
type observable[N int64 | float64] struct {
metric.Observable
- observableID[N]
+ observablID[N]
meter *meter
measures measures[N]
@@ -296,7 +296,7 @@ type observable[N int64 | float64] struct {
func newObservable[N int64 | float64](m *meter, kind InstrumentKind, name, desc, u string) *observable[N] {
return &observable[N]{
- observableID: observableID[N]{
+ observablID: observablID[N]{
name: name,
description: desc,
kind: kind,
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go
index 5647c1db5..891366922 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go
@@ -142,7 +142,7 @@ func (s *sum[N]) cumulative(dest *metricdata.Aggregation) int {
}
// newPrecomputedSum returns an aggregator that summarizes a set of
-// observations as their arithmetic sum. Each sum is scoped by attributes and
+// observatrions as their arithmetic sum. Each sum is scoped by attributes and
// the aggregation cycle the measurements were made in.
func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *precomputedSum[N] {
return &precomputedSum[N]{
@@ -152,7 +152,7 @@ func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() ex
}
}
-// precomputedSum summarizes a set of observations as their arithmetic sum.
+// precomputedSum summarizes a set of observatrions as their arithmetic sum.
type precomputedSum[N int64 | float64] struct {
*valueMap[N]
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go
index 9a047cfa0..9fedfa4be 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go
@@ -41,7 +41,7 @@ func NewFilteredReservoir[N int64 | float64](f Filter, r Reservoir) FilteredRese
func (f *filteredReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) {
if f.filter(ctx) {
- // only record the current time if we are sampling this measurement.
+ // only record the current time if we are sampling this measurment.
f.reservoir.Offer(ctx, time.Now(), NewValue(val), attr)
}
}
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go
index 8cbcff240..199a2608f 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go
@@ -19,7 +19,7 @@
// Do not use crypto/rand. There is no reason for the decrease in performance
// given this is not a security sensitive decision.
rng = rand.New(rand.NewSource(time.Now().UnixNano()))
- // Ensure concurrent safe access to rng and its underlying source.
+ // Ensure concurrent safe accecess to rng and its underlying source.
rngMu sync.Mutex
)
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go b/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go
index abff4650e..2309e5b2b 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go
@@ -459,7 +459,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)
}
continue
}
- reg.registerInt64(o.observableID)
+ reg.registerInt64(o.observablID)
case float64Observable:
if err := o.registerable(m); err != nil {
if !errors.Is(err, errEmptyAgg) {
@@ -467,7 +467,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)
}
continue
}
- reg.registerFloat64(o.observableID)
+ reg.registerFloat64(o.observablID)
default:
// Instrument external to the SDK.
return nil, fmt.Errorf("invalid observable: from different implementation")
@@ -488,14 +488,14 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)
type observer struct {
embedded.Observer
- float64 map[observableID[float64]]struct{}
- int64 map[observableID[int64]]struct{}
+ float64 map[observablID[float64]]struct{}
+ int64 map[observablID[int64]]struct{}
}
func newObserver() observer {
return observer{
- float64: make(map[observableID[float64]]struct{}),
- int64: make(map[observableID[int64]]struct{}),
+ float64: make(map[observablID[float64]]struct{}),
+ int64: make(map[observablID[int64]]struct{}),
}
}
@@ -503,11 +503,11 @@ func (r observer) len() int {
return len(r.float64) + len(r.int64)
}
-func (r observer) registerFloat64(id observableID[float64]) {
+func (r observer) registerFloat64(id observablID[float64]) {
r.float64[id] = struct{}{}
}
-func (r observer) registerInt64(id observableID[int64]) {
+func (r observer) registerInt64(id observablID[int64]) {
r.int64[id] = struct{}{}
}
@@ -536,7 +536,7 @@ func (r observer) ObserveFloat64(o metric.Float64Observable, v float64, opts ...
return
}
- if _, registered := r.float64[oImpl.observableID]; !registered {
+ if _, registered := r.float64[oImpl.observablID]; !registered {
if !oImpl.dropAggregation {
global.Error(errUnregObserver, "failed to record",
"name", oImpl.name,
@@ -571,7 +571,7 @@ func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric
return
}
- if _, registered := r.int64[oImpl.observableID]; !registered {
+ if _, registered := r.int64[oImpl.observablID]; !registered {
if !oImpl.dropAggregation {
global.Error(errUnregObserver, "failed to record",
"name", oImpl.name,
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/version.go b/vendor/go.opentelemetry.io/otel/sdk/metric/version.go
index 45b076408..44316caa1 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/version.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/version.go
@@ -5,5 +5,5 @@
// version is the current release version of the metric SDK in use.
func version() string {
- return "1.30.0"
+ return "1.29.0"
}
diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go
index 3677c83d7..71386e2da 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go
@@ -10,16 +10,17 @@
"golang.org/x/sys/windows/registry"
)
-// implements hostIDReader.
+// implements hostIDReader
type hostIDReaderWindows struct{}
-// read reads MachineGuid from the Windows registry key:
-// SOFTWARE\Microsoft\Cryptography.
+// read reads MachineGuid from the windows registry key:
+// SOFTWARE\Microsoft\Cryptography
func (*hostIDReaderWindows) read() (string, error) {
k, err := registry.OpenKey(
registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`,
registry.QUERY_VALUE|registry.WOW64_64KEY,
)
+
if err != nil {
return "", err
}
diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go b/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go
index a6a5a53c0..5e3d199d7 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go
@@ -17,6 +17,7 @@
func platformOSDescription() (string, error) {
k, err := registry.OpenKey(
registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
+
if err != nil {
return "", err
}
diff --git a/vendor/go.opentelemetry.io/otel/sdk/version.go b/vendor/go.opentelemetry.io/otel/sdk/version.go
index afa4baae8..b7cede891 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/version.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/version.go
@@ -5,5 +5,5 @@
// Version is the current release version of the OpenTelemetry SDK in use.
func Version() string {
- return "1.30.0"
+ return "1.29.0"
}
diff --git a/vendor/go.opentelemetry.io/otel/trace/context.go b/vendor/go.opentelemetry.io/otel/trace/context.go
index 8c45a7107..5650a174b 100644
--- a/vendor/go.opentelemetry.io/otel/trace/context.go
+++ b/vendor/go.opentelemetry.io/otel/trace/context.go
@@ -22,7 +22,7 @@ func ContextWithSpanContext(parent context.Context, sc SpanContext) context.Cont
return ContextWithSpan(parent, nonRecordingSpan{sc: sc})
}
-// ContextWithRemoteSpanContext returns a copy of parent with rsc set explicitly
+// ContextWithRemoteSpanContext returns a copy of parent with rsc set explicly
// as a remote SpanContext and as the current Span. The Span implementation
// that wraps rsc is non-recording and performs no operations other than to
// return rsc as the SpanContext from the SpanContext method.
diff --git a/vendor/go.opentelemetry.io/otel/trace/doc.go b/vendor/go.opentelemetry.io/otel/trace/doc.go
index cdbf41d6d..d661c5d10 100644
--- a/vendor/go.opentelemetry.io/otel/trace/doc.go
+++ b/vendor/go.opentelemetry.io/otel/trace/doc.go
@@ -96,7 +96,7 @@ type TracerProvider struct {
This option is not recommended. It will lead to publishing packages that
contain runtime panics when users update to newer versions of
-[go.opentelemetry.io/otel/trace], which may be done with a transitive
+[go.opentelemetry.io/otel/trace], which may be done with a trasitive
dependency.
Finally, an author can embed another implementation in theirs. The embedded
diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go
index 78b40f3ed..f67039ed1 100644
--- a/vendor/go.opentelemetry.io/otel/version.go
+++ b/vendor/go.opentelemetry.io/otel/version.go
@@ -5,5 +5,5 @@
// Version is the current release version of OpenTelemetry in use.
func Version() string {
- return "1.30.0"
+ return "1.29.0"
}
diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml
index 0c32f4fc4..3ba611d71 100644
--- a/vendor/go.opentelemetry.io/otel/versions.yaml
+++ b/vendor/go.opentelemetry.io/otel/versions.yaml
@@ -3,7 +3,7 @@
module-sets:
stable-v1:
- version: v1.30.0
+ version: v1.29.0
modules:
- go.opentelemetry.io/otel
- go.opentelemetry.io/otel/bridge/opencensus
@@ -29,12 +29,12 @@ module-sets:
- go.opentelemetry.io/otel/sdk/metric
- go.opentelemetry.io/otel/trace
experimental-metrics:
- version: v0.52.0
+ version: v0.51.0
modules:
- go.opentelemetry.io/otel/example/prometheus
- go.opentelemetry.io/otel/exporters/prometheus
experimental-logs:
- version: v0.6.0
+ version: v0.5.0
modules:
- go.opentelemetry.io/otel/log
- go.opentelemetry.io/otel/sdk/log
@@ -42,7 +42,7 @@ module-sets:
- go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
- go.opentelemetry.io/otel/exporters/stdout/stdoutlog
experimental-schema:
- version: v0.0.9
+ version: v0.0.8
modules:
- go.opentelemetry.io/otel/schema
excluded-modules:
diff --git a/vendor/modules.txt b/vendor/modules.txt
index adaadae51..8bad9b85b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -561,7 +561,7 @@ github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
## explicit
github.com/pmezard/go-difflib/difflib
-# github.com/prometheus/client_golang v1.20.3
+# github.com/prometheus/client_golang v1.20.4
## explicit; go 1.20
github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil
github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header
@@ -979,8 +979,8 @@ go.mongodb.org/mongo-driver/bson/bsonrw
go.mongodb.org/mongo-driver/bson/bsontype
go.mongodb.org/mongo-driver/bson/primitive
go.mongodb.org/mongo-driver/x/bsonx/bsoncore
-# go.opentelemetry.io/otel v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel
go.opentelemetry.io/otel/attribute
go.opentelemetry.io/otel/baggage
@@ -999,50 +999,50 @@ go.opentelemetry.io/otel/semconv/v1.20.0/httpconv
go.opentelemetry.io/otel/semconv/v1.24.0
go.opentelemetry.io/otel/semconv/v1.26.0
go.opentelemetry.io/otel/semconv/v1.7.0
-# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace
go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform
-# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry
-# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry
-# go.opentelemetry.io/otel/exporters/prometheus v0.52.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/exporters/prometheus v0.51.0
+## explicit; go 1.21
go.opentelemetry.io/otel/exporters/prometheus
-# go.opentelemetry.io/otel/metric v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/metric v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/metric
go.opentelemetry.io/otel/metric/embedded
go.opentelemetry.io/otel/metric/noop
-# go.opentelemetry.io/otel/sdk v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/sdk v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/sdk
go.opentelemetry.io/otel/sdk/instrumentation
go.opentelemetry.io/otel/sdk/internal/env
go.opentelemetry.io/otel/sdk/internal/x
go.opentelemetry.io/otel/sdk/resource
go.opentelemetry.io/otel/sdk/trace
-# go.opentelemetry.io/otel/sdk/metric v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/sdk/metric v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/sdk/metric
go.opentelemetry.io/otel/sdk/metric/internal
go.opentelemetry.io/otel/sdk/metric/internal/aggregate
go.opentelemetry.io/otel/sdk/metric/internal/exemplar
go.opentelemetry.io/otel/sdk/metric/internal/x
go.opentelemetry.io/otel/sdk/metric/metricdata
-# go.opentelemetry.io/otel/trace v1.30.0
-## explicit; go 1.22
+# go.opentelemetry.io/otel/trace v1.29.0
+## explicit; go 1.21
go.opentelemetry.io/otel/trace
go.opentelemetry.io/otel/trace/embedded
go.opentelemetry.io/otel/trace/noop
diff --git a/web/source/settings/views/admin/instance/settings.tsx b/web/source/settings/views/admin/instance/settings.tsx
index 8d377a6ea..c769b11ec 100644
--- a/web/source/settings/views/admin/instance/settings.tsx
+++ b/web/source/settings/views/admin/instance/settings.tsx
@@ -143,7 +143,7 @@ function InstanceSettingsForm({ data: instance }: InstanceSettingsFormProps) {
@@ -151,7 +151,7 @@ function InstanceSettingsForm({ data: instance }: InstanceSettingsFormProps) {
diff --git a/web/source/settings/views/user/router.tsx b/web/source/settings/views/user/router.tsx
index 86bcf4243..091dd40ae 100644
--- a/web/source/settings/views/user/router.tsx
+++ b/web/source/settings/views/user/router.tsx
@@ -52,10 +52,10 @@ export default function UserRouter() {
+
-
);
@@ -73,13 +73,11 @@ function InteractionRequestsRouter() {
return (
-
-
-
-
-
-
-
+
+
+
+
+
);