mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-22 13:57:51 +00:00
merge main into v3.x
This commit is contained in:
@@ -27,6 +27,7 @@ COPY --from=artifact /etc/ssl/certs /etc/ssl/certs
|
||||
COPY --from=artifact /app/zitadel /app/zitadel
|
||||
|
||||
HEALTHCHECK NONE
|
||||
EXPOSE 8080
|
||||
|
||||
USER zitadel
|
||||
ENTRYPOINT ["/app/zitadel"]
|
||||
ENTRYPOINT ["/app/zitadel"]
|
||||
|
@@ -2,36 +2,26 @@ package setup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
_ "embed"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
)
|
||||
|
||||
type InitPermittedOrgsFunction52 struct {
|
||||
var (
|
||||
//go:embed 52.sql
|
||||
renameTableIfNotExisting string
|
||||
)
|
||||
|
||||
type IDPTemplate6LDAP2 struct {
|
||||
dbClient *database.DB
|
||||
}
|
||||
|
||||
//go:embed 52/*.sql
|
||||
var permittedOrgsFunction52 embed.FS
|
||||
|
||||
func (mig *InitPermittedOrgsFunction52) Execute(ctx context.Context, _ eventstore.Event) error {
|
||||
statements, err := readStatements(permittedOrgsFunction52, "52")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, stmt := range statements {
|
||||
logging.WithFields("file", stmt.file, "migration", mig.String()).Info("execute statement")
|
||||
if _, err := mig.dbClient.ExecContext(ctx, stmt.query); err != nil {
|
||||
return fmt.Errorf("%s %s: %w", mig.String(), stmt.file, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
func (mig *IDPTemplate6LDAP2) Execute(ctx context.Context, _ eventstore.Event) error {
|
||||
_, err := mig.dbClient.ExecContext(ctx, renameTableIfNotExisting)
|
||||
return err
|
||||
}
|
||||
|
||||
func (*InitPermittedOrgsFunction52) String() string {
|
||||
return "52_init_permitted_orgs_function"
|
||||
func (mig *IDPTemplate6LDAP2) String() string {
|
||||
return "52_idp_templates6_ldap2"
|
||||
}
|
||||
|
2
cmd/setup/52.sql
Normal file
2
cmd/setup/52.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE IF EXISTS projections.idp_templates6_ldap3 RENAME COLUMN rootCA TO root_ca;
|
||||
ALTER TABLE IF EXISTS projections.idp_templates6_ldap3 RENAME TO idp_templates6_ldap2;
|
37
cmd/setup/53.go
Normal file
37
cmd/setup/53.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
)
|
||||
|
||||
type InitPermittedOrgsFunction53 struct {
|
||||
dbClient *database.DB
|
||||
}
|
||||
|
||||
//go:embed 53/*.sql
|
||||
var permittedOrgsFunction53 embed.FS
|
||||
|
||||
func (mig *InitPermittedOrgsFunction53) Execute(ctx context.Context, _ eventstore.Event) error {
|
||||
statements, err := readStatements(permittedOrgsFunction53, "53")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, stmt := range statements {
|
||||
logging.WithFields("file", stmt.file, "migration", mig.String()).Info("execute statement")
|
||||
if _, err := mig.dbClient.ExecContext(ctx, stmt.query); err != nil {
|
||||
return fmt.Errorf("%s %s: %w", mig.String(), stmt.file, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*InitPermittedOrgsFunction53) String() string {
|
||||
return "53_init_permitted_orgs_function"
|
||||
}
|
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/notification/handlers"
|
||||
"github.com/zitadel/zitadel/internal/query/projection"
|
||||
static_config "github.com/zitadel/zitadel/internal/static/config"
|
||||
metrics "github.com/zitadel/zitadel/internal/telemetry/metrics/config"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -40,6 +41,7 @@ type Config struct {
|
||||
ExternalPort uint16
|
||||
ExternalSecure bool
|
||||
Log *logging.Config
|
||||
Metrics metrics.Config
|
||||
EncryptionKeys *encryption.EncryptionKeyConfig
|
||||
DefaultInstance command.InstanceSetup
|
||||
Machine *id.Config
|
||||
@@ -88,6 +90,9 @@ func MustNewConfig(v *viper.Viper) *Config {
|
||||
err = config.Log.SetLogger()
|
||||
logging.OnError(err).Fatal("unable to set logger")
|
||||
|
||||
err = config.Metrics.NewMeter()
|
||||
logging.OnError(err).Fatal("unable to set meter")
|
||||
|
||||
id.Configure(config.Machine)
|
||||
|
||||
// Copy the global role permissions mappings to the instance until we allow instance-level configuration over the API.
|
||||
@@ -143,7 +148,8 @@ type Steps struct {
|
||||
s49InitPermittedOrgsFunction *InitPermittedOrgsFunction
|
||||
s50IDPTemplate6UsePKCE *IDPTemplate6UsePKCE
|
||||
s51IDPTemplate6RootCA *IDPTemplate6RootCA
|
||||
s52InitPermittedOrgsFunction *InitPermittedOrgsFunction52
|
||||
s52IDPTemplate6LDAP2 *IDPTemplate6LDAP2
|
||||
s53InitPermittedOrgsFunction *InitPermittedOrgsFunction52
|
||||
}
|
||||
|
||||
func MustNewSteps(v *viper.Viper) *Steps {
|
||||
|
@@ -178,7 +178,8 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string)
|
||||
steps.s49InitPermittedOrgsFunction = &InitPermittedOrgsFunction{eventstoreClient: dbClient}
|
||||
steps.s50IDPTemplate6UsePKCE = &IDPTemplate6UsePKCE{dbClient: dbClient}
|
||||
steps.s51IDPTemplate6RootCA = &IDPTemplate6RootCA{dbClient: dbClient}
|
||||
steps.s52InitPermittedOrgsFunction = &InitPermittedOrgsFunction52{dbClient: dbClient}
|
||||
steps.s52IDPTemplate6LDAP2 = &IDPTemplate6LDAP2{dbClient: dbClient}
|
||||
steps.s53InitPermittedOrgsFunction = &InitPermittedOrgsFunction52{dbClient: dbClient}
|
||||
|
||||
err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil, nil)
|
||||
logging.OnError(err).Fatal("unable to start projections")
|
||||
@@ -219,7 +220,8 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string)
|
||||
steps.s49InitPermittedOrgsFunction,
|
||||
steps.s50IDPTemplate6UsePKCE,
|
||||
steps.s51IDPTemplate6RootCA,
|
||||
steps.s52InitPermittedOrgsFunction,
|
||||
steps.s52IDPTemplate6LDAP2,
|
||||
steps.s53InitPermittedOrgsFunction,
|
||||
} {
|
||||
mustExecuteMigration(ctx, eventstoreClient, step, "migration failed")
|
||||
}
|
||||
|
@@ -3464,7 +3464,7 @@
|
||||
"@zitadel/proto" "1.0.4"
|
||||
jose "^5.3.0"
|
||||
|
||||
"@zitadel/proto@1.0.4", "@zitadel/proto@^1.0.4":
|
||||
"@zitadel/proto@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@zitadel/proto/-/proto-1.0.4.tgz#e2fe9895f2960643c3619191255aa2f4913ad873"
|
||||
integrity sha512-s13ZMhuOTe0b+geV+JgJud+kpYdq7TgkuCe7RIY+q4Xs5KC0FHMKfvbAk/jpFbD+TSQHiwo/TBNZlGHdwUR9Ig==
|
||||
|
@@ -8156,9 +8156,9 @@ mz@^2.7.0:
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nanoid@^3.3.7:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
version "3.3.8"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
|
||||
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
|
||||
|
||||
negotiator@0.6.3:
|
||||
version "0.6.3"
|
||||
|
@@ -181,9 +181,9 @@ aws4@^1.8.0:
|
||||
integrity sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==
|
||||
|
||||
axios@^1.6.1:
|
||||
version "1.7.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2"
|
||||
integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==
|
||||
version "1.8.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.4.tgz#78990bb4bc63d2cae072952d374835950a82f447"
|
||||
integrity sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.6"
|
||||
form-data "^4.0.0"
|
||||
|
2
go.mod
2
go.mod
@@ -74,7 +74,7 @@ require (
|
||||
github.com/zitadel/logging v0.6.2
|
||||
github.com/zitadel/oidc/v3 v3.36.1
|
||||
github.com/zitadel/passwap v0.7.0
|
||||
github.com/zitadel/saml v0.3.4
|
||||
github.com/zitadel/saml v0.3.5
|
||||
github.com/zitadel/schema v1.3.1
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0
|
||||
|
4
go.sum
4
go.sum
@@ -809,8 +809,8 @@ github.com/zitadel/oidc/v3 v3.36.1 h1:1AT1NqKKEqAwx4GmKJZ9fYkWH2WIn/VKMfQ46nBtRf
|
||||
github.com/zitadel/oidc/v3 v3.36.1/go.mod h1:dApGZLvWZTHRuxmcbQlW5d2XVjVYR3vGOdq536igmTs=
|
||||
github.com/zitadel/passwap v0.7.0 h1:TQTr9TV75PLATGICor1g5hZDRNHRvB9t0Hn4XkiR7xQ=
|
||||
github.com/zitadel/passwap v0.7.0/go.mod h1:/NakQNYahdU+YFEitVD6mlm8BLfkiIT+IM5wgClRoAY=
|
||||
github.com/zitadel/saml v0.3.4 h1:L2pybnx2Hs+kqebZmUbnZUd9L/CY2sNw5psMWw2D/6Q=
|
||||
github.com/zitadel/saml v0.3.4/go.mod h1:M0losAULJpLtAmXrYqBnf375ia2rMgJ75b1mpaU/GlA=
|
||||
github.com/zitadel/saml v0.3.5 h1:L1RKWS5y66cGepVxUGjx/WSBOtrtSpRA/J3nn5BJLOY=
|
||||
github.com/zitadel/saml v0.3.5/go.mod h1:ybs3e4tIWdYgSYBpuCsvf3T4FNDfbXYM+GPv5vIpHYk=
|
||||
github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
|
||||
github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
|
@@ -10,7 +10,7 @@ import (
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/oidc"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@@ -158,7 +158,11 @@ func (s *Server) linkSessionToAuthRequest(ctx context.Context, authRequestID str
|
||||
return nil, err
|
||||
}
|
||||
authReq := &oidc.AuthRequestV2{CurrentAuthRequest: aar}
|
||||
ctx = op.ContextWithIssuer(ctx, http.DomainContext(ctx).Origin())
|
||||
issuer := authReq.Issuer
|
||||
if issuer == "" {
|
||||
issuer = http_utils.DomainContext(ctx).Origin()
|
||||
}
|
||||
ctx = op.ContextWithIssuer(ctx, issuer)
|
||||
var callback string
|
||||
if aar.ResponseType == domain.OIDCResponseTypeCode {
|
||||
callback, err = oidc.CreateCodeCallbackURL(ctx, authReq, s.op.Provider())
|
||||
|
@@ -4,9 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
"github.com/zitadel/saml/pkg/provider"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/saml"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@@ -76,6 +78,11 @@ func (s *Server) linkSessionToSAMLRequest(ctx context.Context, samlRequestID str
|
||||
return nil, err
|
||||
}
|
||||
authReq := &saml.AuthRequestV2{CurrentSAMLRequest: aar}
|
||||
responseIssuer := authReq.ResponseIssuer
|
||||
if responseIssuer == "" {
|
||||
responseIssuer = http_utils.DomainContext(ctx).Origin()
|
||||
}
|
||||
ctx = provider.ContextWithIssuer(ctx, responseIssuer)
|
||||
url, body, err := s.idp.CreateResponse(ctx, authReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -111,6 +111,7 @@ func (o *OPStorage) createAuthRequestLoginClient(ctx context.Context, req *oidc.
|
||||
Prompt: PromptToBusiness(req.Prompt),
|
||||
UILocales: UILocalesToBusiness(req.UILocales),
|
||||
MaxAge: MaxAgeToBusiness(req.MaxAge),
|
||||
Issuer: o.contextToIssuer(ctx),
|
||||
}
|
||||
if req.LoginHint != "" {
|
||||
authRequest.LoginHint = &req.LoginHint
|
||||
|
@@ -75,6 +75,7 @@ type OPStorage struct {
|
||||
encAlg crypto.EncryptionAlgorithm
|
||||
locker crdb.Locker
|
||||
assetAPIPrefix func(ctx context.Context) string
|
||||
contextToIssuer func(context.Context) string
|
||||
}
|
||||
|
||||
// Provider is used to overload certain [op.Provider] methods
|
||||
@@ -119,7 +120,7 @@ func NewServer(
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "OIDC-EGrqd", "cannot create op config: %w")
|
||||
}
|
||||
storage := newStorage(config, command, query, repo, encryptionAlg, es, projections)
|
||||
storage := newStorage(config, command, query, repo, encryptionAlg, es, projections, ContextToIssuer)
|
||||
keyCache := newPublicKeyCache(ctx, config.PublicKeyCacheMaxAge, queryKeyFunc(query))
|
||||
accessTokenKeySet := newOidcKeySet(keyCache, withKeyExpiryCheck(true))
|
||||
idTokenHintKeySet := newOidcKeySet(keyCache)
|
||||
@@ -182,9 +183,13 @@ func NewServer(
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func ContextToIssuer(ctx context.Context) string {
|
||||
return http_utils.DomainContext(ctx).Origin()
|
||||
}
|
||||
|
||||
func IssuerFromContext(_ bool) (op.IssuerFromRequest, error) {
|
||||
return func(r *http.Request) string {
|
||||
return http_utils.DomainContext(r.Context()).Origin()
|
||||
return ContextToIssuer(r.Context())
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -220,7 +225,7 @@ func createOPConfig(config Config, defaultLogoutRedirectURI string, cryptoKey []
|
||||
return opConfig, nil
|
||||
}
|
||||
|
||||
func newStorage(config Config, command *command.Commands, query *query.Queries, repo repository.Repository, encAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, db *database.DB) *OPStorage {
|
||||
func newStorage(config Config, command *command.Commands, query *query.Queries, repo repository.Repository, encAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, db *database.DB, contextToIssuer func(context.Context) string) *OPStorage {
|
||||
return &OPStorage{
|
||||
repo: repo,
|
||||
command: command,
|
||||
@@ -236,6 +241,7 @@ func newStorage(config Config, command *command.Commands, query *query.Queries,
|
||||
encAlg: encAlg,
|
||||
locker: crdb.NewLocker(db.DB, locksTable, signingKey),
|
||||
assetAPIPrefix: assets.AssetAPI(),
|
||||
contextToIssuer: contextToIssuer,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,6 @@ package saml
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/zitadel/saml/pkg/provider"
|
||||
@@ -34,15 +33,9 @@ func (p *Provider) CreateResponse(ctx context.Context, authReq models.AuthReques
|
||||
AcsUrl: authReq.GetAccessConsumerServiceURL(),
|
||||
RequestID: authReq.GetAuthRequestID(),
|
||||
Audience: authReq.GetIssuer(),
|
||||
Issuer: p.GetEntityID(ctx),
|
||||
}
|
||||
|
||||
issuer := ContextToIssuer(ctx)
|
||||
req, err := http.NewRequestWithContext(provider.ContextWithIssuer(ctx, issuer), http.MethodGet, issuer, nil)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
resp.Issuer = p.GetEntityID(req)
|
||||
|
||||
samlResponse, err := p.AuthCallbackResponse(ctx, authReq, resp)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
|
@@ -60,6 +60,7 @@ func NewProvider(
|
||||
projections,
|
||||
fmt.Sprintf("%s%s?%s=", login.HandlerPrefix, login.EndpointLogin, login.QueryAuthRequestID),
|
||||
conf.DefaultLoginURLV2,
|
||||
ContextToIssuer,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -117,6 +118,7 @@ func newStorage(
|
||||
db *database.DB,
|
||||
defaultLoginURL string,
|
||||
defaultLoginURLV2 string,
|
||||
contextToIssuer func(context.Context) string,
|
||||
) (*Storage, error) {
|
||||
return &Storage{
|
||||
encAlg: encAlg,
|
||||
@@ -128,6 +130,7 @@ func newStorage(
|
||||
query: query,
|
||||
defaultLoginURL: defaultLoginURL,
|
||||
defaultLoginURLv2: defaultLoginURLV2,
|
||||
contextToIssuer: contextToIssuer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,7 @@ type Storage struct {
|
||||
|
||||
defaultLoginURL string
|
||||
defaultLoginURLv2 string
|
||||
contextToIssuer func(context.Context) string
|
||||
}
|
||||
|
||||
func (p *Storage) GetEntityByID(ctx context.Context, entityID string) (*serviceprovider.ServiceProvider, error) {
|
||||
@@ -137,14 +138,15 @@ func (p *Storage) createAuthRequestLoginClient(ctx context.Context, req *samlp.A
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
samlRequest := &command.SAMLRequest{
|
||||
ApplicationID: applicationID,
|
||||
ACSURL: acsUrl,
|
||||
RelayState: relayState,
|
||||
RequestID: req.Id,
|
||||
Binding: protocolBinding,
|
||||
Issuer: req.Issuer.Text,
|
||||
Destination: req.Destination,
|
||||
LoginClient: loginClient,
|
||||
ApplicationID: applicationID,
|
||||
ACSURL: acsUrl,
|
||||
RelayState: relayState,
|
||||
RequestID: req.Id,
|
||||
Binding: protocolBinding,
|
||||
Issuer: req.Issuer.Text,
|
||||
Destination: req.Destination,
|
||||
LoginClient: loginClient,
|
||||
ResponseIssuer: p.contextToIssuer(ctx),
|
||||
}
|
||||
|
||||
aar, err := p.command.AddSAMLRequest(ctx, samlRequest)
|
||||
|
@@ -29,6 +29,7 @@ type AuthRequest struct {
|
||||
LoginHint *string
|
||||
HintUserID *string
|
||||
NeedRefreshToken bool
|
||||
Issuer string
|
||||
}
|
||||
|
||||
type CurrentAuthRequest struct {
|
||||
@@ -73,6 +74,7 @@ func (c *Commands) AddAuthRequest(ctx context.Context, authRequest *AuthRequest)
|
||||
authRequest.LoginHint,
|
||||
authRequest.HintUserID,
|
||||
authRequest.NeedRefreshToken,
|
||||
authRequest.Issuer,
|
||||
))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -180,6 +182,7 @@ func authRequestWriteModelToCurrentAuthRequest(writeModel *AuthRequestWriteModel
|
||||
MaxAge: writeModel.MaxAge,
|
||||
LoginHint: writeModel.LoginHint,
|
||||
HintUserID: writeModel.HintUserID,
|
||||
Issuer: writeModel.Issuer,
|
||||
},
|
||||
SessionID: writeModel.SessionID,
|
||||
UserID: writeModel.UserID,
|
||||
|
@@ -36,6 +36,7 @@ type AuthRequestWriteModel struct {
|
||||
AuthMethods []domain.UserAuthMethodType
|
||||
AuthRequestState domain.AuthRequestState
|
||||
NeedRefreshToken bool
|
||||
Issuer string
|
||||
}
|
||||
|
||||
func NewAuthRequestWriteModel(ctx context.Context, id string) *AuthRequestWriteModel {
|
||||
@@ -68,6 +69,7 @@ func (m *AuthRequestWriteModel) Reduce() error {
|
||||
m.HintUserID = e.HintUserID
|
||||
m.AuthRequestState = domain.AuthRequestStateAdded
|
||||
m.NeedRefreshToken = e.NeedRefreshToken
|
||||
m.Issuer = e.Issuer
|
||||
case *authrequest.SessionLinkedEvent:
|
||||
m.SessionID = e.SessionID
|
||||
m.UserID = e.UserID
|
||||
|
@@ -62,6 +62,7 @@ func TestCommands_AddAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -101,6 +102,7 @@ func TestCommands_AddAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
false,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -127,6 +129,7 @@ func TestCommands_AddAuthRequest(t *testing.T) {
|
||||
MaxAge: gu.Ptr(time.Duration(0)),
|
||||
LoginHint: gu.Ptr("loginHint"),
|
||||
HintUserID: gu.Ptr("hintUserID"),
|
||||
Issuer: "issuer",
|
||||
},
|
||||
},
|
||||
&CurrentAuthRequest{
|
||||
@@ -150,6 +153,7 @@ func TestCommands_AddAuthRequest(t *testing.T) {
|
||||
MaxAge: gu.Ptr(time.Duration(0)),
|
||||
LoginHint: gu.Ptr("loginHint"),
|
||||
HintUserID: gu.Ptr("hintUserID"),
|
||||
Issuer: "issuer",
|
||||
},
|
||||
},
|
||||
nil,
|
||||
@@ -234,6 +238,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -276,6 +281,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -317,6 +323,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -356,6 +363,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -418,6 +426,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -469,6 +478,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -527,6 +537,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
Audience: []string{"audience"},
|
||||
ResponseType: domain.OIDCResponseTypeCode,
|
||||
ResponseMode: domain.OIDCResponseModeQuery,
|
||||
Issuer: "issuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -557,6 +568,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -616,6 +628,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
Audience: []string{"audience"},
|
||||
ResponseType: domain.OIDCResponseTypeCode,
|
||||
ResponseMode: domain.OIDCResponseModeQuery,
|
||||
Issuer: "issuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -646,6 +659,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -706,6 +720,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
Audience: []string{"audience"},
|
||||
ResponseType: domain.OIDCResponseTypeCode,
|
||||
ResponseMode: domain.OIDCResponseModeQuery,
|
||||
Issuer: "issuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -736,6 +751,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -797,6 +813,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
Audience: []string{"audience"},
|
||||
ResponseType: domain.OIDCResponseTypeCode,
|
||||
ResponseMode: domain.OIDCResponseModeQuery,
|
||||
Issuer: "issuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -827,6 +844,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -950,6 +968,7 @@ func TestCommands_FailAuthRequest(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -978,6 +997,7 @@ func TestCommands_FailAuthRequest(t *testing.T) {
|
||||
Audience: []string{"audience"},
|
||||
ResponseType: domain.OIDCResponseTypeCode,
|
||||
ResponseMode: domain.OIDCResponseModeQuery,
|
||||
Issuer: "issuer",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1050,6 +1070,7 @@ func TestCommands_AddAuthRequestCode(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -1088,6 +1109,7 @@ func TestCommands_AddAuthRequestCode(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
|
@@ -138,6 +138,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -182,6 +183,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -234,6 +236,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -331,6 +334,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -465,6 +469,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -610,6 +615,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
true,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -748,6 +754,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
gu.Ptr("loginHint"),
|
||||
gu.Ptr("hintUserID"),
|
||||
false,
|
||||
"issuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
|
@@ -15,13 +15,14 @@ type SAMLRequest struct {
|
||||
ID string
|
||||
LoginClient string
|
||||
|
||||
ApplicationID string
|
||||
ACSURL string
|
||||
RelayState string
|
||||
RequestID string
|
||||
Binding string
|
||||
Issuer string
|
||||
Destination string
|
||||
ApplicationID string
|
||||
ACSURL string
|
||||
RelayState string
|
||||
RequestID string
|
||||
Binding string
|
||||
Issuer string
|
||||
Destination string
|
||||
ResponseIssuer string
|
||||
}
|
||||
|
||||
type CurrentSAMLRequest struct {
|
||||
@@ -56,6 +57,7 @@ func (c *Commands) AddSAMLRequest(ctx context.Context, samlRequest *SAMLRequest)
|
||||
samlRequest.Binding,
|
||||
samlRequest.Issuer,
|
||||
samlRequest.Destination,
|
||||
samlRequest.ResponseIssuer,
|
||||
))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -131,15 +133,16 @@ func (c *Commands) FailSAMLRequest(ctx context.Context, id string, reason domain
|
||||
func samlRequestWriteModelToCurrentSAMLRequest(writeModel *SAMLRequestWriteModel) (_ *CurrentSAMLRequest) {
|
||||
return &CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: writeModel.AggregateID,
|
||||
LoginClient: writeModel.LoginClient,
|
||||
ApplicationID: writeModel.ApplicationID,
|
||||
ACSURL: writeModel.ACSURL,
|
||||
RelayState: writeModel.RelayState,
|
||||
RequestID: writeModel.RequestID,
|
||||
Binding: writeModel.Binding,
|
||||
Issuer: writeModel.Issuer,
|
||||
Destination: writeModel.Destination,
|
||||
ID: writeModel.AggregateID,
|
||||
LoginClient: writeModel.LoginClient,
|
||||
ApplicationID: writeModel.ApplicationID,
|
||||
ACSURL: writeModel.ACSURL,
|
||||
RelayState: writeModel.RelayState,
|
||||
RequestID: writeModel.RequestID,
|
||||
Binding: writeModel.Binding,
|
||||
Issuer: writeModel.Issuer,
|
||||
Destination: writeModel.Destination,
|
||||
ResponseIssuer: writeModel.ResponseIssuer,
|
||||
},
|
||||
SessionID: writeModel.SessionID,
|
||||
UserID: writeModel.UserID,
|
||||
|
@@ -15,14 +15,15 @@ type SAMLRequestWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
aggregate *eventstore.Aggregate
|
||||
|
||||
LoginClient string
|
||||
ApplicationID string
|
||||
ACSURL string
|
||||
RelayState string
|
||||
RequestID string
|
||||
Binding string
|
||||
Issuer string
|
||||
Destination string
|
||||
LoginClient string
|
||||
ApplicationID string
|
||||
ACSURL string
|
||||
RelayState string
|
||||
RequestID string
|
||||
Binding string
|
||||
Issuer string
|
||||
Destination string
|
||||
ResponseIssuer string
|
||||
|
||||
SessionID string
|
||||
UserID string
|
||||
@@ -52,6 +53,7 @@ func (m *SAMLRequestWriteModel) Reduce() error {
|
||||
m.Binding = e.Binding
|
||||
m.Issuer = e.Issuer
|
||||
m.Destination = e.Destination
|
||||
m.ResponseIssuer = e.ResponseIssuer
|
||||
m.SAMLRequestState = domain.SAMLRequestStateAdded
|
||||
case *samlrequest.SessionLinkedEvent:
|
||||
m.SessionID = e.SessionID
|
||||
|
@@ -54,6 +54,7 @@ func TestCommands_AddSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -82,6 +83,7 @@ func TestCommands_AddSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -90,27 +92,29 @@ func TestCommands_AddSAMLRequest(t *testing.T) {
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
request: &SAMLRequest{
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
},
|
||||
&CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: "V2_id",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ID: "V2_id",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
},
|
||||
nil,
|
||||
@@ -187,6 +191,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -222,6 +227,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -255,6 +261,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -286,6 +293,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -340,6 +348,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -383,6 +392,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -431,15 +441,16 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
details: &domain.ObjectDetails{ResourceOwner: "instanceID"},
|
||||
authReq: &CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: "V2_id",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ID: "V2_id",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -462,6 +473,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -511,15 +523,16 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
details: &domain.ObjectDetails{ResourceOwner: "instanceID"},
|
||||
authReq: &CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: "V2_id",
|
||||
LoginClient: "loginClient",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ID: "V2_id",
|
||||
LoginClient: "loginClient",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -541,6 +554,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -591,15 +605,16 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
details: &domain.ObjectDetails{ResourceOwner: "instanceID"},
|
||||
authReq: &CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: "V2_id",
|
||||
LoginClient: "loginClient",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ID: "V2_id",
|
||||
LoginClient: "loginClient",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -622,6 +637,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -672,15 +688,16 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
details: &domain.ObjectDetails{ResourceOwner: "instanceID"},
|
||||
authReq: &CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: "V2_id",
|
||||
LoginClient: "loginClient",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ID: "V2_id",
|
||||
LoginClient: "loginClient",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
UserID: "userID",
|
||||
@@ -703,6 +720,7 @@ func TestCommands_LinkSessionToSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -817,6 +835,7 @@ func TestCommands_FailSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
samlrequest.NewFailedEvent(mockCtx, &samlrequest.NewAggregate("V2_id", "instanceID").Aggregate,
|
||||
@@ -850,6 +869,7 @@ func TestCommands_FailSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -870,15 +890,16 @@ func TestCommands_FailSAMLRequest(t *testing.T) {
|
||||
details: &domain.ObjectDetails{ResourceOwner: "instanceID"},
|
||||
samlReq: &CurrentSAMLRequest{
|
||||
SAMLRequest: &SAMLRequest{
|
||||
ID: "V2_id",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ID: "V2_id",
|
||||
LoginClient: "login",
|
||||
ApplicationID: "application",
|
||||
ACSURL: "acs",
|
||||
RelayState: "relaystate",
|
||||
RequestID: "request",
|
||||
Binding: "binding",
|
||||
Issuer: "issuer",
|
||||
Destination: "destination",
|
||||
ResponseIssuer: "responseissuer",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -99,6 +99,7 @@ func TestCommands_CreateSAMLSessionFromSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -129,6 +130,7 @@ func TestCommands_CreateSAMLSessionFromSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -167,6 +169,7 @@ func TestCommands_CreateSAMLSessionFromSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -248,6 +251,7 @@ func TestCommands_CreateSAMLSessionFromSAMLRequest(t *testing.T) {
|
||||
"binding",
|
||||
"issuer",
|
||||
"destination",
|
||||
"responseissuer",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
|
@@ -67,6 +67,8 @@ type Handler struct {
|
||||
cacheInvalidations []func(ctx context.Context, aggregates []*eventstore.Aggregate)
|
||||
|
||||
queryInstances func() ([]string, error)
|
||||
|
||||
metrics *ProjectionMetrics
|
||||
}
|
||||
|
||||
var _ migration.Migration = (*Handler)(nil)
|
||||
@@ -159,6 +161,8 @@ func NewHandler(
|
||||
aggregates[reducer.Aggregate] = eventTypes
|
||||
}
|
||||
|
||||
metrics := NewProjectionMetrics()
|
||||
|
||||
handler := &Handler{
|
||||
projection: projection,
|
||||
client: config.Client,
|
||||
@@ -178,6 +182,7 @@ func NewHandler(
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
metrics: metrics,
|
||||
}
|
||||
|
||||
return handler
|
||||
@@ -483,6 +488,8 @@ func (h *Handler) processEvents(ctx context.Context, config *triggerConfig) (add
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
|
||||
tx, err := h.client.BeginTx(txCtx, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -502,7 +509,7 @@ func (h *Handler) processEvents(ctx context.Context, config *triggerConfig) (add
|
||||
}
|
||||
return additionalIteration, err
|
||||
}
|
||||
// stop execution if currentState.eventTimestamp >= config.maxCreatedAt
|
||||
// stop execution if currentState.position >= config.maxPosition
|
||||
if config.maxPosition != 0 && currentState.position >= config.maxPosition {
|
||||
return false, nil
|
||||
}
|
||||
@@ -518,7 +525,14 @@ func (h *Handler) processEvents(ctx context.Context, config *triggerConfig) (add
|
||||
if err == nil {
|
||||
err = commitErr
|
||||
}
|
||||
|
||||
h.metrics.ProjectionEventsProcessed(ctx, h.ProjectionName(), int64(len(statements)), err == nil)
|
||||
|
||||
if err == nil && currentState.aggregateID != "" && len(statements) > 0 {
|
||||
// Don't update projection timing or latency unless we successfully processed events
|
||||
h.metrics.ProjectionUpdateTiming(ctx, h.ProjectionName(), float64(time.Since(start).Seconds()))
|
||||
h.metrics.ProjectionStateLatency(ctx, h.ProjectionName(), time.Since(currentState.eventTimestamp).Seconds())
|
||||
|
||||
h.invalidateCaches(ctx, aggregatesFromStatements(statements))
|
||||
}
|
||||
}()
|
||||
@@ -540,6 +554,7 @@ func (h *Handler) processEvents(ctx context.Context, config *triggerConfig) (add
|
||||
currentState.aggregateType = statements[lastProcessedIndex].Aggregate.Type
|
||||
currentState.sequence = statements[lastProcessedIndex].Sequence
|
||||
currentState.eventTimestamp = statements[lastProcessedIndex].CreationDate
|
||||
|
||||
err = h.setState(tx, currentState)
|
||||
|
||||
return additionalIteration, err
|
||||
|
70
internal/eventstore/handler/v2/metrics.go
Normal file
70
internal/eventstore/handler/v2/metrics.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
ProjectionLabel = "projection"
|
||||
SuccessLabel = "success"
|
||||
|
||||
ProjectionEventsProcessed = "projection_events_processed"
|
||||
ProjectionHandleTimerMetric = "projection_handle_timer"
|
||||
ProjectionStateLatencyMetric = "projection_state_latency"
|
||||
)
|
||||
|
||||
type ProjectionMetrics struct {
|
||||
provider metrics.Metrics
|
||||
}
|
||||
|
||||
func NewProjectionMetrics() *ProjectionMetrics {
|
||||
projectionMetrics := &ProjectionMetrics{provider: metrics.M}
|
||||
|
||||
err := projectionMetrics.provider.RegisterCounter(
|
||||
ProjectionEventsProcessed,
|
||||
"Number of events reduced to process projection updates",
|
||||
)
|
||||
logging.OnError(err).Error("failed to register projection events processed counter")
|
||||
err = projectionMetrics.provider.RegisterHistogram(
|
||||
ProjectionHandleTimerMetric,
|
||||
"Time taken to process a projection update",
|
||||
"s",
|
||||
[]float64{0.005, 0.01, 0.05, 0.1, 1, 5, 10, 30, 60, 120},
|
||||
)
|
||||
logging.OnError(err).Error("failed to register projection handle timer metric")
|
||||
err = projectionMetrics.provider.RegisterHistogram(
|
||||
ProjectionStateLatencyMetric,
|
||||
"When finishing processing a batch of events, this track the age of the last events seen from current time",
|
||||
"s",
|
||||
[]float64{0.1, 0.5, 1, 5, 10, 30, 60, 300, 600, 1800},
|
||||
)
|
||||
logging.OnError(err).Error("failed to register projection state latency metric")
|
||||
return projectionMetrics
|
||||
}
|
||||
|
||||
func (m *ProjectionMetrics) ProjectionUpdateTiming(ctx context.Context, projection string, duration float64) {
|
||||
err := m.provider.AddHistogramMeasurement(ctx, ProjectionHandleTimerMetric, duration, map[string]attribute.Value{
|
||||
ProjectionLabel: attribute.StringValue(projection),
|
||||
})
|
||||
logging.OnError(err).Error("failed to add projection trigger timing")
|
||||
}
|
||||
|
||||
func (m *ProjectionMetrics) ProjectionEventsProcessed(ctx context.Context, projection string, count int64, success bool) {
|
||||
err := m.provider.AddCount(ctx, ProjectionEventsProcessed, count, map[string]attribute.Value{
|
||||
ProjectionLabel: attribute.StringValue(projection),
|
||||
SuccessLabel: attribute.BoolValue(success),
|
||||
})
|
||||
logging.OnError(err).Error("failed to add projection events processed metric")
|
||||
}
|
||||
|
||||
func (m *ProjectionMetrics) ProjectionStateLatency(ctx context.Context, projection string, latency float64) {
|
||||
err := m.provider.AddHistogramMeasurement(ctx, ProjectionStateLatencyMetric, latency, map[string]attribute.Value{
|
||||
ProjectionLabel: attribute.StringValue(projection),
|
||||
})
|
||||
logging.OnError(err).Error("failed to add projection state latency metric")
|
||||
}
|
132
internal/eventstore/handler/v2/metrics_test.go
Normal file
132
internal/eventstore/handler/v2/metrics_test.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics"
|
||||
)
|
||||
|
||||
func TestNewProjectionMetrics(t *testing.T) {
|
||||
mockMetrics := metrics.NewMockMetrics()
|
||||
metrics.M = mockMetrics
|
||||
|
||||
metrics := NewProjectionMetrics()
|
||||
require.NotNil(t, metrics)
|
||||
assert.NotNil(t, metrics.provider)
|
||||
}
|
||||
|
||||
func TestProjectionMetrics_ProjectionUpdateTiming(t *testing.T) {
|
||||
|
||||
mockMetrics := metrics.NewMockMetrics()
|
||||
metrics.M = mockMetrics
|
||||
projectionMetrics := NewProjectionMetrics()
|
||||
|
||||
ctx := context.Background()
|
||||
projection := "test_projection"
|
||||
duration := 0.5
|
||||
|
||||
projectionMetrics.ProjectionUpdateTiming(ctx, projection, duration)
|
||||
|
||||
values := mockMetrics.GetHistogramValues(ProjectionHandleTimerMetric)
|
||||
require.Len(t, values, 1)
|
||||
assert.Equal(t, duration, values[0])
|
||||
|
||||
labels := mockMetrics.GetHistogramLabels(ProjectionHandleTimerMetric)
|
||||
require.Len(t, labels, 1)
|
||||
assert.Equal(t, projection, labels[0][ProjectionLabel].AsString())
|
||||
}
|
||||
|
||||
func TestProjectionMetrics_ProjectionEventsProcessed(t *testing.T) {
|
||||
|
||||
mockMetrics := metrics.NewMockMetrics()
|
||||
metrics.M = mockMetrics
|
||||
projectionMetrics := NewProjectionMetrics()
|
||||
|
||||
ctx := context.Background()
|
||||
projection := "test_projection"
|
||||
count := int64(5)
|
||||
success := true
|
||||
|
||||
projectionMetrics.ProjectionEventsProcessed(ctx, projection, count, success)
|
||||
|
||||
value := mockMetrics.GetCounterValue(ProjectionEventsProcessed)
|
||||
assert.Equal(t, count, value)
|
||||
|
||||
labels := mockMetrics.GetCounterLabels(ProjectionEventsProcessed)
|
||||
require.Len(t, labels, 1)
|
||||
assert.Equal(t, projection, labels[0][ProjectionLabel].AsString())
|
||||
assert.Equal(t, success, labels[0][SuccessLabel].AsBool())
|
||||
}
|
||||
|
||||
func TestProjectionMetrics_ProjectionStateLatency(t *testing.T) {
|
||||
|
||||
mockMetrics := metrics.NewMockMetrics()
|
||||
metrics.M = mockMetrics
|
||||
projectionMetrics := NewProjectionMetrics()
|
||||
|
||||
ctx := context.Background()
|
||||
projection := "test_projection"
|
||||
latency := 10.0
|
||||
|
||||
projectionMetrics.ProjectionStateLatency(ctx, projection, latency)
|
||||
|
||||
values := mockMetrics.GetHistogramValues(ProjectionStateLatencyMetric)
|
||||
require.Len(t, values, 1)
|
||||
assert.Equal(t, latency, values[0])
|
||||
|
||||
labels := mockMetrics.GetHistogramLabels(ProjectionStateLatencyMetric)
|
||||
require.Len(t, labels, 1)
|
||||
assert.Equal(t, projection, labels[0][ProjectionLabel].AsString())
|
||||
}
|
||||
|
||||
func TestProjectionMetrics_Integration(t *testing.T) {
|
||||
|
||||
mockMetrics := metrics.NewMockMetrics()
|
||||
metrics.M = mockMetrics
|
||||
projectionMetrics := NewProjectionMetrics()
|
||||
|
||||
ctx := context.Background()
|
||||
projection := "test_projection"
|
||||
|
||||
start := time.Now()
|
||||
|
||||
projectionMetrics.ProjectionEventsProcessed(ctx, projection, 3, true)
|
||||
projectionMetrics.ProjectionEventsProcessed(ctx, projection, 1, false)
|
||||
|
||||
duration := time.Since(start).Seconds()
|
||||
projectionMetrics.ProjectionUpdateTiming(ctx, projection, duration)
|
||||
|
||||
latency := 5.0
|
||||
projectionMetrics.ProjectionStateLatency(ctx, projection, latency)
|
||||
|
||||
value := mockMetrics.GetCounterValue(ProjectionEventsProcessed)
|
||||
assert.Equal(t, int64(4), value)
|
||||
|
||||
timingValues := mockMetrics.GetHistogramValues(ProjectionHandleTimerMetric)
|
||||
require.Len(t, timingValues, 1)
|
||||
assert.Equal(t, duration, timingValues[0])
|
||||
|
||||
latencyValues := mockMetrics.GetHistogramValues(ProjectionStateLatencyMetric)
|
||||
require.Len(t, latencyValues, 1)
|
||||
assert.Equal(t, latency, latencyValues[0])
|
||||
|
||||
eventsLabels := mockMetrics.GetCounterLabels(ProjectionEventsProcessed)
|
||||
require.Len(t, eventsLabels, 2)
|
||||
assert.Equal(t, projection, eventsLabels[0][ProjectionLabel].AsString())
|
||||
assert.Equal(t, true, eventsLabels[0][SuccessLabel].AsBool())
|
||||
assert.Equal(t, projection, eventsLabels[1][ProjectionLabel].AsString())
|
||||
assert.Equal(t, false, eventsLabels[1][SuccessLabel].AsBool())
|
||||
|
||||
timingLabels := mockMetrics.GetHistogramLabels(ProjectionHandleTimerMetric)
|
||||
require.Len(t, timingLabels, 1)
|
||||
assert.Equal(t, projection, timingLabels[0][ProjectionLabel].AsString())
|
||||
|
||||
latencyLabels := mockMetrics.GetHistogramLabels(ProjectionStateLatencyMetric)
|
||||
require.Len(t, latencyLabels, 1)
|
||||
assert.Equal(t, projection, latencyLabels[0][ProjectionLabel].AsString())
|
||||
}
|
@@ -38,6 +38,7 @@ type AddedEvent struct {
|
||||
LoginHint *string `json:"login_hint,omitempty"`
|
||||
HintUserID *string `json:"hint_user_id,omitempty"`
|
||||
NeedRefreshToken bool `json:"need_refresh_token,omitempty"`
|
||||
Issuer string `json:"issuer,omitempty"`
|
||||
}
|
||||
|
||||
func (e *AddedEvent) Payload() interface{} {
|
||||
@@ -66,6 +67,7 @@ func NewAddedEvent(ctx context.Context,
|
||||
loginHint,
|
||||
hintUserID *string,
|
||||
needRefreshToken bool,
|
||||
issuer string,
|
||||
) *AddedEvent {
|
||||
return &AddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@@ -89,6 +91,7 @@ func NewAddedEvent(ctx context.Context,
|
||||
LoginHint: loginHint,
|
||||
HintUserID: hintUserID,
|
||||
NeedRefreshToken: needRefreshToken,
|
||||
Issuer: issuer,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,14 +19,15 @@ const (
|
||||
type AddedEvent struct {
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
|
||||
LoginClient string `json:"login_client,omitempty"`
|
||||
ApplicationID string `json:"application_id,omitempty"`
|
||||
ACSURL string `json:"acs_url,omitempty"`
|
||||
RelayState string `json:"relay_state,omitempty"`
|
||||
RequestID string `json:"request_id,omitempty"`
|
||||
Binding string `json:"binding,omitempty"`
|
||||
Issuer string `json:"issuer,omitempty"`
|
||||
Destination string `json:"destination,omitempty"`
|
||||
LoginClient string `json:"login_client,omitempty"`
|
||||
ApplicationID string `json:"application_id,omitempty"`
|
||||
ACSURL string `json:"acs_url,omitempty"`
|
||||
RelayState string `json:"relay_state,omitempty"`
|
||||
RequestID string `json:"request_id,omitempty"`
|
||||
Binding string `json:"binding,omitempty"`
|
||||
Issuer string `json:"issuer,omitempty"`
|
||||
Destination string `json:"destination,omitempty"`
|
||||
ResponseIssuer string `json:"response_issuer,omitempty"`
|
||||
}
|
||||
|
||||
func (e *AddedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
@@ -51,6 +52,7 @@ func NewAddedEvent(ctx context.Context,
|
||||
binding string,
|
||||
issuer string,
|
||||
destination string,
|
||||
responseIssuer string,
|
||||
) *AddedEvent {
|
||||
return &AddedEvent{
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
@@ -58,14 +60,15 @@ func NewAddedEvent(ctx context.Context,
|
||||
aggregate,
|
||||
AddedType,
|
||||
),
|
||||
LoginClient: loginClient,
|
||||
ApplicationID: applicationID,
|
||||
ACSURL: acsURL,
|
||||
RelayState: relayState,
|
||||
RequestID: requestID,
|
||||
Binding: binding,
|
||||
Issuer: issuer,
|
||||
Destination: destination,
|
||||
LoginClient: loginClient,
|
||||
ApplicationID: applicationID,
|
||||
ACSURL: acsURL,
|
||||
RelayState: relayState,
|
||||
RequestID: requestID,
|
||||
Binding: binding,
|
||||
Issuer: issuer,
|
||||
Destination: destination,
|
||||
ResponseIssuer: responseIssuer,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics/otel"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@@ -12,11 +13,16 @@ type Config struct {
|
||||
|
||||
var meter = map[string]func(map[string]interface{}) error{
|
||||
"otel": otel.NewTracerFromConfig,
|
||||
"none": NoMetrics,
|
||||
"": NoMetrics,
|
||||
"none": registerNoopMetrics,
|
||||
"": registerNoopMetrics,
|
||||
}
|
||||
|
||||
func (c *Config) NewMeter() error {
|
||||
// When using start-from-init or start-from-setup the metric provider
|
||||
// was already set in the setup phase and the start phase must not overwrite it.
|
||||
if metrics.M != nil {
|
||||
return nil
|
||||
}
|
||||
t, ok := meter[c.Type]
|
||||
if !ok {
|
||||
return zerrors.ThrowInternalf(nil, "METER-Dfqsx", "config type %s not supported", c.Type)
|
||||
@@ -25,6 +31,7 @@ func (c *Config) NewMeter() error {
|
||||
return t(c.Config)
|
||||
}
|
||||
|
||||
func NoMetrics(_ map[string]interface{}) error {
|
||||
func registerNoopMetrics(rawConfig map[string]interface{}) (err error) {
|
||||
metrics.M = &metrics.NoopMetrics{}
|
||||
return nil
|
||||
}
|
||||
|
@@ -22,8 +22,10 @@ type Metrics interface {
|
||||
GetMetricsProvider() metric.MeterProvider
|
||||
RegisterCounter(name, description string) error
|
||||
AddCount(ctx context.Context, name string, value int64, labels map[string]attribute.Value) error
|
||||
AddHistogramMeasurement(ctx context.Context, name string, value float64, labels map[string]attribute.Value) error
|
||||
RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64Callback) error
|
||||
RegisterValueObserver(name, description string, callbackFunc metric.Int64Callback) error
|
||||
RegisterHistogram(name, description, unit string, buckets []float64) error
|
||||
}
|
||||
|
||||
var M Metrics
|
||||
@@ -56,6 +58,20 @@ func AddCount(ctx context.Context, name string, value int64, labels map[string]a
|
||||
return M.AddCount(ctx, name, value, labels)
|
||||
}
|
||||
|
||||
func AddHistogramMeasurement(ctx context.Context, name string, value float64, labels map[string]attribute.Value) error {
|
||||
if M == nil {
|
||||
return nil
|
||||
}
|
||||
return M.AddHistogramMeasurement(ctx, name, value, labels)
|
||||
}
|
||||
|
||||
func RegisterHistogram(name, description, unit string, buckets []float64) error {
|
||||
if M == nil {
|
||||
return nil
|
||||
}
|
||||
return M.RegisterHistogram(name, description, unit, buckets)
|
||||
}
|
||||
|
||||
func RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64Callback) error {
|
||||
if M == nil {
|
||||
return nil
|
||||
|
95
internal/telemetry/metrics/mock.go
Normal file
95
internal/telemetry/metrics/mock.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
// MockMetrics implements the metrics.Metrics interface for testing
|
||||
type MockMetrics struct {
|
||||
mu sync.RWMutex
|
||||
histogramValues map[string][]float64
|
||||
counterValues map[string]int64
|
||||
histogramLabels map[string][]map[string]attribute.Value
|
||||
counterLabels map[string][]map[string]attribute.Value
|
||||
}
|
||||
|
||||
var _ Metrics = new(MockMetrics)
|
||||
|
||||
// NewMockMetrics creates a new Metrics instance for testing
|
||||
func NewMockMetrics() *MockMetrics {
|
||||
return &MockMetrics{
|
||||
histogramValues: make(map[string][]float64),
|
||||
counterValues: make(map[string]int64),
|
||||
histogramLabels: make(map[string][]map[string]attribute.Value),
|
||||
counterLabels: make(map[string][]map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockMetrics) GetExporter() http.Handler {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) GetMetricsProvider() metric.MeterProvider {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) RegisterCounter(name, description string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) AddCount(ctx context.Context, name string, value int64, labels map[string]attribute.Value) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.counterValues[name] += value
|
||||
m.counterLabels[name] = append(m.counterLabels[name], labels)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) AddHistogramMeasurement(ctx context.Context, name string, value float64, labels map[string]attribute.Value) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.histogramValues[name] = append(m.histogramValues[name], value)
|
||||
m.histogramLabels[name] = append(m.histogramLabels[name], labels)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64Callback) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) RegisterValueObserver(name, description string, callbackFunc metric.Int64Callback) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) RegisterHistogram(name, description, unit string, buckets []float64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockMetrics) GetHistogramValues(name string) []float64 {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.histogramValues[name]
|
||||
}
|
||||
|
||||
func (m *MockMetrics) GetHistogramLabels(name string) []map[string]attribute.Value {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.histogramLabels[name]
|
||||
}
|
||||
|
||||
func (m *MockMetrics) GetCounterValue(name string) int64 {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.counterValues[name]
|
||||
}
|
||||
|
||||
func (m *MockMetrics) GetCounterLabels(name string) []map[string]attribute.Value {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.counterLabels[name]
|
||||
}
|
45
internal/telemetry/metrics/noop.go
Normal file
45
internal/telemetry/metrics/noop.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
type NoopMetrics struct{}
|
||||
|
||||
var _ Metrics = new(NoopMetrics)
|
||||
|
||||
func (n *NoopMetrics) GetExporter() http.Handler {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) GetMetricsProvider() metric.MeterProvider {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) RegisterCounter(name, description string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) AddCount(ctx context.Context, name string, value int64, labels map[string]attribute.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) AddHistogramMeasurement(ctx context.Context, name string, value float64, labels map[string]attribute.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64Callback) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) RegisterValueObserver(name, description string, callbackFunc metric.Int64Callback) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NoopMetrics) RegisterHistogram(name, description, unit string, buckets []float64) error {
|
||||
return nil
|
||||
}
|
@@ -24,6 +24,7 @@ type Metrics struct {
|
||||
Counters sync.Map
|
||||
UpDownSumObserver sync.Map
|
||||
ValueObservers sync.Map
|
||||
Histograms sync.Map
|
||||
}
|
||||
|
||||
func NewMetrics(meterName string) (metrics.Metrics, error) {
|
||||
@@ -84,6 +85,33 @@ func (m *Metrics) AddCount(ctx context.Context, name string, value int64, labels
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Metrics) AddHistogramMeasurement(ctx context.Context, name string, value float64, labels map[string]attribute.Value) error {
|
||||
histogram, exists := m.Histograms.Load(name)
|
||||
if !exists {
|
||||
return zerrors.ThrowNotFound(nil, "METER-5wwb1", "Errors.Metrics.Histogram.NotFound")
|
||||
}
|
||||
histogram.(metric.Float64Histogram).Record(ctx, value, MapToRecordOption(labels)...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Metrics) RegisterHistogram(name, description, unit string, buckets []float64) error {
|
||||
if _, exists := m.Histograms.Load(name); exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
histogram, err := m.Meter.Float64Histogram(name,
|
||||
metric.WithDescription(description),
|
||||
metric.WithUnit(unit),
|
||||
metric.WithExplicitBucketBoundaries(buckets...),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Histograms.Store(name, histogram)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Metrics) RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64Callback) error {
|
||||
if _, exists := m.UpDownSumObserver.Load(name); exists {
|
||||
return nil
|
||||
@@ -113,15 +141,23 @@ func (m *Metrics) RegisterValueObserver(name, description string, callbackFunc m
|
||||
}
|
||||
|
||||
func MapToAddOption(labels map[string]attribute.Value) []metric.AddOption {
|
||||
return []metric.AddOption{metric.WithAttributes(labelsToAttributes(labels)...)}
|
||||
}
|
||||
|
||||
func MapToRecordOption(labels map[string]attribute.Value) []metric.RecordOption {
|
||||
return []metric.RecordOption{metric.WithAttributes(labelsToAttributes(labels)...)}
|
||||
}
|
||||
|
||||
func labelsToAttributes(labels map[string]attribute.Value) []attribute.KeyValue {
|
||||
if labels == nil {
|
||||
return nil
|
||||
}
|
||||
keyValues := make([]attribute.KeyValue, 0, len(labels))
|
||||
attributes := make([]attribute.KeyValue, 0, len(labels))
|
||||
for key, value := range labels {
|
||||
keyValues = append(keyValues, attribute.KeyValue{
|
||||
attributes = append(attributes, attribute.KeyValue{
|
||||
Key: attribute.Key(key),
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return []metric.AddOption{metric.WithAttributes(keyValues...)}
|
||||
return attributes
|
||||
}
|
||||
|
Reference in New Issue
Block a user