mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-11 10:46:25 +03:00
add postgres query to traces
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/10853 GitOrigin-RevId: b47c7077fc8fc7115ab05dffe93195abfeb4131d
This commit is contained in:
parent
8bc5c01961
commit
cf41d2abd9
@ -1229,6 +1229,19 @@ This sets transaction isolation.
|
||||
| **Default** | `read-committed` |
|
||||
| **Supported in** | Deprecated in versions > `v2.0.0` |
|
||||
|
||||
### Trace SQL Queries
|
||||
|
||||
Add SQL queries to the OTLP traces.
|
||||
|
||||
| | |
|
||||
| ------------------- | ---------------------------------------- |
|
||||
| **Flag** | `--trace-sql-query` |
|
||||
| **Env var** | `HASURA_GRAPHQL_ENABLE_QUERY_TRACING` |
|
||||
| **Accepted values** | Boolean |
|
||||
| **Options** | `true` or `false` |
|
||||
| **Default** | `false` |
|
||||
| **Supported in** | CE, Enterprise Edition |
|
||||
|
||||
### Unauthorized Role
|
||||
|
||||
This identifies an [unauthorized role](/auth/authentication/unauthenticated-access.mdx), used when the
|
||||
|
@ -332,7 +332,8 @@ serveOptions =
|
||||
soPersistedQueries = Init._default Init.persistedQueriesOption,
|
||||
soPersistedQueriesTtl = Init._default Init.persistedQueriesTtlOption,
|
||||
soRemoteSchemaResponsePriority = Init._default Init.remoteSchemaResponsePriorityOption,
|
||||
soHeaderPrecedence = Init._default Init.configuredHeaderPrecedenceOption
|
||||
soHeaderPrecedence = Init._default Init.configuredHeaderPrecedenceOption,
|
||||
soTraceQueryStatus = Init._default Init.traceQueryStatusOption
|
||||
}
|
||||
|
||||
-- | What log level should be used by the engine; this is not exported, and
|
||||
|
@ -174,7 +174,8 @@ data AppContext = AppContext
|
||||
acCloseWebsocketsOnMetadataChangeStatus :: CloseWebsocketsOnMetadataChangeStatus,
|
||||
acSchemaSampledFeatureFlags :: SchemaSampledFeatureFlags,
|
||||
acRemoteSchemaResponsePriority :: RemoteSchemaResponsePriority,
|
||||
acHeaderPrecedence :: HeaderPrecedence
|
||||
acHeaderPrecedence :: HeaderPrecedence,
|
||||
acTraceQueryStatus :: TraceQueryStatus
|
||||
}
|
||||
|
||||
-- | Collection of the LoggerCtx, the regular Logger and the PGLogger
|
||||
@ -297,7 +298,8 @@ buildAppContextRule = proc (ServeOptions {..}, env, _keys, checkFeatureFlag) ->
|
||||
acCloseWebsocketsOnMetadataChangeStatus = soCloseWebsocketsOnMetadataChangeStatus,
|
||||
acSchemaSampledFeatureFlags = schemaSampledFeatureFlags,
|
||||
acRemoteSchemaResponsePriority = soRemoteSchemaResponsePriority,
|
||||
acHeaderPrecedence = soHeaderPrecedence
|
||||
acHeaderPrecedence = soHeaderPrecedence,
|
||||
acTraceQueryStatus = soTraceQueryStatus
|
||||
}
|
||||
where
|
||||
buildEventEngineCtx = Inc.cache proc (httpPoolSize, fetchInterval, fetchBatchSize) -> do
|
||||
|
@ -38,7 +38,7 @@ import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Schema.Options qualified as Options
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Server.Types (HeaderPrecedence)
|
||||
import Hasura.Server.Types (HeaderPrecedence, TraceQueryStatus)
|
||||
import Hasura.Session
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Network.HTTP.Client as HTTP
|
||||
@ -78,8 +78,9 @@ bqDBQueryPlan ::
|
||||
QueryDB 'BigQuery Void (UnpreparedValue 'BigQuery) ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo 'BigQuery, [ModelInfoPart])
|
||||
bqDBQueryPlan userInfo sourceName sourceConfig qrf _ _ = do
|
||||
bqDBQueryPlan userInfo sourceName sourceConfig qrf _ _ _ = do
|
||||
-- TODO (naveen): Append query tags to the query
|
||||
select <- planNoPlan (BigQuery.bigQuerySourceConfigToFromIrConfig sourceConfig) userInfo qrf
|
||||
let action = OnBaseMonad do
|
||||
@ -147,8 +148,9 @@ bqDBMutationPlan ::
|
||||
Maybe G.Name ->
|
||||
Maybe (HashMap G.Name (G.Value G.Variable)) ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo 'BigQuery, [ModelInfoPart])
|
||||
bqDBMutationPlan _env _manager _logger _userInfo _stringifyNum _sourceName _sourceConfig _mrf _headers _gName _maybeSelSetArgs _ =
|
||||
bqDBMutationPlan _env _manager _logger _userInfo _stringifyNum _sourceName _sourceConfig _mrf _headers _gName _maybeSelSetArgs _ _traceQueryStatus =
|
||||
throw500 "mutations are not supported in BigQuery; this should be unreachable"
|
||||
|
||||
-- explain
|
||||
@ -230,9 +232,10 @@ bqDBRemoteRelationshipPlan ::
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
Options.StringifyNumbers ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo 'BigQuery, [ModelInfoPart])
|
||||
bqDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship reqHeaders operationName stringifyNumbers = do
|
||||
(dbStepInfo, modelInfo) <- flip runReaderT emptyQueryTagsComment $ bqDBQueryPlan userInfo sourceName sourceConfig rootSelection reqHeaders operationName
|
||||
bqDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship reqHeaders operationName stringifyNumbers traceQueryStatus = do
|
||||
(dbStepInfo, modelInfo) <- flip runReaderT emptyQueryTagsComment $ bqDBQueryPlan userInfo sourceName sourceConfig rootSelection reqHeaders operationName traceQueryStatus
|
||||
pure (dbStepInfo, modelInfo)
|
||||
where
|
||||
coerceToColumn = BigQuery.ColumnName . getFieldNameTxt
|
||||
|
@ -54,7 +54,7 @@ instance BackendExecute 'DataConnector where
|
||||
type MultiplexedQuery 'DataConnector = Void
|
||||
type ExecutionMonad 'DataConnector = AgentClientT
|
||||
|
||||
mkDBQueryPlan UserInfo {..} sourceName sourceConfig ir _headers _gName = do
|
||||
mkDBQueryPlan UserInfo {..} sourceName sourceConfig ir _headers _gName _traceQueryStatus = do
|
||||
queryPlan@Plan {..} <- flip runReaderT (API._cScalarTypes $ _scCapabilities sourceConfig, _uiSession) $ Plan.mkQueryPlan ir
|
||||
transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession)
|
||||
modelNames <- irToModelInfoGen sourceName ModelSourceTypeDataConnector ir
|
||||
@ -84,7 +84,7 @@ instance BackendExecute 'DataConnector where
|
||||
dbsiResolvedConnectionTemplate = ()
|
||||
}
|
||||
|
||||
mkDBMutationPlan _env _manager _logger UserInfo {..} _stringifyNum sourceName sourceConfig mutationDB _headers _gName _maybeSelSetArgs _ = do
|
||||
mkDBMutationPlan _env _manager _logger UserInfo {..} _stringifyNum sourceName sourceConfig mutationDB _headers _gName _maybeSelSetArgs _ _traceQueryStatus = do
|
||||
(mutationPlan@Plan {..}, modelNames) <- flip runReaderT (API._cScalarTypes $ _scCapabilities sourceConfig, _uiSession) $ Plan.mkMutationPlan sourceName ModelSourceTypeDataConnector mutationDB
|
||||
transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession)
|
||||
let modelInfo = getModelInfoPartfromModelNames modelNames (ModelOperationType G.OperationTypeMutation)
|
||||
@ -105,7 +105,7 @@ instance BackendExecute 'DataConnector where
|
||||
mkDBStreamingSubscriptionPlan _ _ _ _ _ _ =
|
||||
throw400 NotSupported "mkLiveQuerySubscriptionPlan: not implemented for the Data Connector backend."
|
||||
|
||||
mkDBRemoteRelationshipPlan UserInfo {..} sourceName sourceConfig joinIds joinIdsSchema argumentIdFieldName (resultFieldName, ir) _ _ _ = do
|
||||
mkDBRemoteRelationshipPlan UserInfo {..} sourceName sourceConfig joinIds joinIdsSchema argumentIdFieldName (resultFieldName, ir) _ _ _ _ = do
|
||||
(remoteRelationshipPlan@Plan {..}, modelInfo) <- flip runReaderT (API._cScalarTypes $ _scCapabilities sourceConfig, _uiSession) $ Plan.mkRemoteRelationshipPlan sourceName sourceConfig joinIds joinIdsSchema argumentIdFieldName resultFieldName ir
|
||||
transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession)
|
||||
pure
|
||||
|
@ -55,7 +55,7 @@ import Hasura.RQL.Types.Column qualified as RQLColumn
|
||||
import Hasura.RQL.Types.Common as RQLTypes
|
||||
import Hasura.RQL.Types.Schema.Options qualified as Options
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Server.Types (HeaderPrecedence)
|
||||
import Hasura.Server.Types (HeaderPrecedence, TraceQueryStatus)
|
||||
import Hasura.Session
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Network.HTTP.Client as HTTP
|
||||
@ -100,8 +100,9 @@ msDBQueryPlan ::
|
||||
QueryDB 'MSSQL Void (UnpreparedValue 'MSSQL) ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo 'MSSQL, [ModelInfoPart])
|
||||
msDBQueryPlan userInfo sourceName sourceConfig qrf _ _ = do
|
||||
msDBQueryPlan userInfo sourceName sourceConfig qrf _ _ _ = do
|
||||
let sessionVariables = _uiSession userInfo
|
||||
QueryWithDDL {qwdBeforeSteps, qwdAfterSteps, qwdQuery = statement} <- planQuery sessionVariables qrf
|
||||
queryTags <- ask
|
||||
@ -319,8 +320,9 @@ msDBMutationPlan ::
|
||||
Maybe G.Name ->
|
||||
Maybe (HashMap G.Name (G.Value G.Variable)) ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo 'MSSQL, [ModelInfoPart])
|
||||
msDBMutationPlan _env _manager _logger userInfo stringifyNum sourceName sourceConfig mrf _headers _gName _maybeSelSetArgs _ = do
|
||||
msDBMutationPlan _env _manager _logger userInfo stringifyNum sourceName sourceConfig mrf _headers _gName _maybeSelSetArgs _ _ = do
|
||||
go <$> case mrf of
|
||||
MDBInsert annInsert -> executeInsert userInfo stringifyNum sourceName ModelSourceTypeMSSQL sourceConfig annInsert
|
||||
MDBDelete annDelete -> executeDelete userInfo stringifyNum sourceName ModelSourceTypeMSSQL sourceConfig annDelete
|
||||
@ -525,8 +527,9 @@ msDBRemoteRelationshipPlan ::
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
Options.StringifyNumbers ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo 'MSSQL, [ModelInfoPart])
|
||||
msDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship _headers _gName _stringifyNumbers = do
|
||||
msDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship _headers _gName _stringifyNumbers _traceQueryStatus = do
|
||||
-- `stringifyNumbers` is not currently handled in any SQL Server operation
|
||||
statement <- planSourceRelationship (_uiSession userInfo) lhs lhsSchema argumentId relationship
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
-- This module includes the Postgres implementation of queries, mutations, and more.
|
||||
module Hasura.Backends.Postgres.Instances.Execute
|
||||
( PreparedSql (..),
|
||||
pgDBQueryPlanSimple,
|
||||
)
|
||||
where
|
||||
|
||||
@ -93,7 +92,7 @@ import Hasura.RQL.Types.Common (FieldName (..), JsonAggSelect (..), SourceName (
|
||||
import Hasura.RQL.Types.Permission (ValidateInput (..), ValidateInputHttpDefinition (..))
|
||||
import Hasura.RQL.Types.Schema.Options qualified as Options
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Server.Types (HeaderPrecedence)
|
||||
import Hasura.Server.Types (HeaderPrecedence, TraceQueryStatus (TraceQueryEnabled))
|
||||
import Hasura.Session (UserInfo (..))
|
||||
import Hasura.Tracing qualified as Tracing
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
@ -140,8 +139,9 @@ pgDBQueryPlan ::
|
||||
QueryDB ('Postgres pgKind) Void (UnpreparedValue ('Postgres pgKind)) ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
m ((DBStepInfo ('Postgres pgKind)), [ModelInfoPart])
|
||||
pgDBQueryPlan userInfo sourceName sourceConfig qrf reqHeaders operationName = do
|
||||
pgDBQueryPlan userInfo sourceName sourceConfig qrf reqHeaders operationName traceQueryStatus = do
|
||||
(preparedQuery, PlanningSt {_psPrepped = planVals}) <-
|
||||
flip runStateT initPlanningSt $ traverse (prepareWithPlan userInfo) qrf
|
||||
queryTagsComment <- ask
|
||||
@ -157,26 +157,9 @@ pgDBQueryPlan userInfo sourceName sourceConfig qrf reqHeaders operationName = do
|
||||
modelNames <- irToModelInfoGen sourceName ModelSourceTypePostgres preparedQuery
|
||||
let modelInfo = getModelInfoPartfromModelNames modelNames (ModelOperationType G.OperationTypeQuery)
|
||||
let preparedSQLWithQueryTags = appendPreparedSQLWithQueryTags rootFieldPlan queryTagsComment
|
||||
let (action, preparedSQL) = mkCurPlanTx userInfo preparedSQLWithQueryTags
|
||||
let (action, preparedSQL) = mkCurPlanTx userInfo preparedSQLWithQueryTags traceQueryStatus
|
||||
pure $ (DBStepInfo @('Postgres pgKind) sourceName sourceConfig preparedSQL (fmap withNoStatistics action) resolvedConnectionTemplate, modelInfo)
|
||||
|
||||
-- | Used by the @dc-postgres-agent to compile a query.
|
||||
pgDBQueryPlanSimple ::
|
||||
(MonadError QErr m, MonadIO m) =>
|
||||
UserInfo ->
|
||||
QueryTagsComment ->
|
||||
QueryDB ('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla)) ->
|
||||
m (OnBaseMonad (PG.TxET QErr) EncJSON, Maybe PreparedSql)
|
||||
pgDBQueryPlanSimple userInfo queryTagsComment query = do
|
||||
(preparedQuery, PlanningSt {_psPrepped = planVals}) <-
|
||||
flip runStateT initPlanningSt $ traverse (prepareWithPlan userInfo) query
|
||||
rootFieldPlan <- irToRootFieldPlan userInfo planVals preparedQuery
|
||||
-- seems like this function is not being used anywhere in graphql-engine, so we're not going to count the models used
|
||||
let preparedSQLWithQueryTags =
|
||||
appendPreparedSQLWithQueryTags rootFieldPlan queryTagsComment
|
||||
let (action, preparedSQL) = mkCurPlanTx userInfo preparedSQLWithQueryTags
|
||||
pure (action, preparedSQL)
|
||||
|
||||
pgDBQueryExplain ::
|
||||
forall pgKind m.
|
||||
( MonadError QErr m,
|
||||
@ -401,11 +384,12 @@ convertFunction ::
|
||||
SourceName ->
|
||||
ModelSourceType ->
|
||||
UserInfo ->
|
||||
TraceQueryStatus ->
|
||||
JsonAggSelect ->
|
||||
-- | VOLATILE function as 'SelectExp'
|
||||
IR.AnnSimpleSelectG ('Postgres pgKind) Void (UnpreparedValue ('Postgres pgKind)) ->
|
||||
m (OnBaseMonad (PG.TxET QErr) EncJSON, [ModelNameInfo])
|
||||
convertFunction sourceName modelSourceType userInfo jsonAggSelect unpreparedQuery = do
|
||||
convertFunction sourceName modelSourceType userInfo traceQueryStatus jsonAggSelect unpreparedQuery = do
|
||||
queryTags <- ask
|
||||
-- Transform the RQL AST into a prepared SQL query
|
||||
(preparedQuery, PlanningSt {_psPrepped = planVals}) <-
|
||||
@ -419,7 +403,7 @@ convertFunction sourceName modelSourceType userInfo jsonAggSelect unpreparedQuer
|
||||
modelNames <- irToModelInfoGen sourceName modelSourceType $ queryResultFn preparedQuery
|
||||
let preparedSQLWithQueryTags = appendPreparedSQLWithQueryTags rootFieldPlan queryTags
|
||||
pure
|
||||
( fst (mkCurPlanTx userInfo preparedSQLWithQueryTags), -- forget (Maybe PreparedSql)
|
||||
( fst (mkCurPlanTx userInfo preparedSQLWithQueryTags traceQueryStatus), -- forget (Maybe PreparedSql)
|
||||
modelNames
|
||||
)
|
||||
|
||||
@ -444,8 +428,9 @@ pgDBMutationPlan ::
|
||||
Maybe G.Name ->
|
||||
Maybe (HashMap G.Name (G.Value G.Variable)) ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo ('Postgres pgKind), [ModelInfoPart])
|
||||
pgDBMutationPlan env manager logger userInfo stringifyNum sourceName sourceConfig mrf reqHeaders operationName selSetArguments headerPrecedence = do
|
||||
pgDBMutationPlan env manager logger userInfo stringifyNum sourceName sourceConfig mrf reqHeaders operationName selSetArguments headerPrecedence traceQueryStatus = do
|
||||
resolvedConnectionTemplate <-
|
||||
let connectionTemplateResolver =
|
||||
connectionTemplateConfigResolver (_pscConnectionTemplateConfig sourceConfig)
|
||||
@ -458,7 +443,7 @@ pgDBMutationPlan env manager logger userInfo stringifyNum sourceName sourceConfi
|
||||
MDBInsert s -> convertInsert sourceName ModelSourceTypePostgres env manager logger userInfo s stringifyNum reqHeaders headerPrecedence
|
||||
MDBUpdate s -> convertUpdate sourceName ModelSourceTypePostgres env manager logger userInfo s stringifyNum reqHeaders selSetArguments headerPrecedence
|
||||
MDBDelete s -> convertDelete sourceName ModelSourceTypePostgres env manager logger userInfo s stringifyNum reqHeaders selSetArguments headerPrecedence
|
||||
MDBFunction returnsSet s -> convertFunction sourceName ModelSourceTypePostgres userInfo returnsSet s
|
||||
MDBFunction returnsSet s -> convertFunction sourceName ModelSourceTypePostgres userInfo traceQueryStatus returnsSet s
|
||||
where
|
||||
modelInfoList v = getModelInfoPartfromModelNames (snd v) (ModelOperationType G.OperationTypeMutation)
|
||||
go resolvedConnectionTemplate v =
|
||||
@ -647,8 +632,9 @@ testMultiplexedQueryTx (PGL.MultiplexedQuery query) cohortId cohortVariables = d
|
||||
mkCurPlanTx ::
|
||||
UserInfo ->
|
||||
PreparedSql ->
|
||||
TraceQueryStatus ->
|
||||
(OnBaseMonad (PG.TxET QErr) EncJSON, Maybe PreparedSql)
|
||||
mkCurPlanTx userInfo ps@(PreparedSql q prepMap) =
|
||||
mkCurPlanTx userInfo ps@(PreparedSql q prepMap) traceQueryStatus =
|
||||
-- generate the SQL and prepared vars or the bytestring
|
||||
let args = withUserVars (_uiSession userInfo) prepMap
|
||||
-- WARNING: this quietly assumes the intmap keys are contiguous
|
||||
@ -656,6 +642,8 @@ mkCurPlanTx userInfo ps@(PreparedSql q prepMap) =
|
||||
in (,Just ps) $ OnBaseMonad do
|
||||
-- https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/database/#connection-level-attributes
|
||||
Tracing.attachMetadata [("db.system", "postgresql")]
|
||||
when (traceQueryStatus == TraceQueryEnabled)
|
||||
$ Tracing.attachMetadata [("db.query", PG.getQueryText q)]
|
||||
runIdentity
|
||||
. PG.getRow
|
||||
<$> PG.rawQE dmlTxErrorHandler q prepArgs True
|
||||
@ -724,14 +712,15 @@ pgDBRemoteRelationshipPlan ::
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
Options.StringifyNumbers ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo ('Postgres pgKind), [ModelInfoPart])
|
||||
pgDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship reqHeaders operationName stringifyNumbers = do
|
||||
pgDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship reqHeaders operationName stringifyNumbers traceQueryStatus = do
|
||||
-- NOTE: 'QueryTags' currently cannot support remote relationship queries.
|
||||
--
|
||||
-- In the future if we want to add support we'll need to add a new type of
|
||||
-- metadata (e.g. 'ParameterizedQueryHash' doesn't make sense here) and find
|
||||
-- a root field name that makes sense to attach to it.
|
||||
(dbStepInfo, modelInfo) <- flip runReaderT emptyQueryTagsComment $ pgDBQueryPlan userInfo sourceName sourceConfig rootSelection reqHeaders operationName
|
||||
(dbStepInfo, modelInfo) <- flip runReaderT emptyQueryTagsComment $ pgDBQueryPlan userInfo sourceName sourceConfig rootSelection reqHeaders operationName traceQueryStatus
|
||||
pure (dbStepInfo, modelInfo)
|
||||
where
|
||||
coerceToColumn = Postgres.unsafePGCol . getFieldNameTxt
|
||||
|
@ -63,7 +63,7 @@ import Hasura.RQL.Types.Subscription
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Server.Init qualified as Init
|
||||
import Hasura.Server.Prometheus (PrometheusMetrics)
|
||||
import Hasura.Server.Types (HeaderPrecedence, MonadGetPolicies, ReadOnlyMode (..), RequestId (..))
|
||||
import Hasura.Server.Types (HeaderPrecedence, MonadGetPolicies, ReadOnlyMode (..), RequestId (..), TraceQueryStatus)
|
||||
import Hasura.Services
|
||||
import Hasura.Session (BackendOnlyFieldAccess (..), UserInfo (..))
|
||||
import Hasura.Tracing qualified as Tracing
|
||||
@ -364,6 +364,7 @@ getResolvedExecPlan ::
|
||||
RequestId ->
|
||||
Init.ResponseInternalErrorsConfig ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (ParameterizedQueryHash, ResolvedExecutionPlan, [ModelInfoPart])
|
||||
getResolvedExecPlan
|
||||
env
|
||||
@ -380,7 +381,8 @@ getResolvedExecPlan
|
||||
maybeOperationName
|
||||
reqId
|
||||
responseErrorsConfig
|
||||
headerPrecedence = do
|
||||
headerPrecedence
|
||||
traceQueryStatus = do
|
||||
let gCtx = makeGQLContext userInfo sc queryType
|
||||
tracesPropagator = getOtelTracesPropagator $ scOpenTelemetryConfig sc
|
||||
|
||||
@ -407,6 +409,7 @@ getResolvedExecPlan
|
||||
maybeOperationName
|
||||
responseErrorsConfig
|
||||
headerPrecedence
|
||||
traceQueryStatus
|
||||
Tracing.attachMetadata [("graphql.operation.type", "query"), ("parameterized_query_hash", bsToTxt $ unParamQueryHash parameterizedQueryHash)]
|
||||
pure (parameterizedQueryHash, QueryExecutionPlan executionPlan queryRootFields dirMap, modelInfoList)
|
||||
G.TypedOperationDefinition G.OperationTypeMutation _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve mutation execution plan" $ do
|
||||
@ -430,6 +433,7 @@ getResolvedExecPlan
|
||||
reqId
|
||||
maybeOperationName
|
||||
headerPrecedence
|
||||
traceQueryStatus
|
||||
Tracing.attachMetadata [("graphql.operation.type", "mutation")]
|
||||
pure (parameterizedQueryHash, MutationExecutionPlan executionPlan, modelInfoList)
|
||||
G.TypedOperationDefinition G.OperationTypeSubscription _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve subscription execution plan" $ do
|
||||
|
@ -82,6 +82,7 @@ class
|
||||
QueryDB b Void (UnpreparedValue b) ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
m ((DBStepInfo b), [ModelInfoPart])
|
||||
mkDBMutationPlan ::
|
||||
forall m.
|
||||
@ -103,6 +104,7 @@ class
|
||||
Maybe G.Name ->
|
||||
Maybe (HashMap G.Name (G.Value G.Variable)) ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo b, [ModelInfoPart])
|
||||
mkLiveQuerySubscriptionPlan ::
|
||||
forall m.
|
||||
@ -178,6 +180,7 @@ class
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
Options.StringifyNumbers ->
|
||||
TraceQueryStatus ->
|
||||
m (DBStepInfo b, [ModelInfoPart])
|
||||
|
||||
-- | This is a helper function to convert a remote source's relationship to a
|
||||
|
@ -98,6 +98,7 @@ convertMutationSelectionSet ::
|
||||
-- | Graphql Operation Name
|
||||
Maybe G.Name ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (ExecutionPlan, ParameterizedQueryHash, [ModelInfoPart])
|
||||
convertMutationSelectionSet
|
||||
env
|
||||
@ -115,7 +116,8 @@ convertMutationSelectionSet
|
||||
introspectionDisabledRoles
|
||||
reqId
|
||||
maybeOperationName
|
||||
headerPrecedence = do
|
||||
headerPrecedence
|
||||
traceQueryStatus = do
|
||||
mutationParser <-
|
||||
onNothing (gqlMutationParser gqlContext)
|
||||
$ throw400 ValidationFailed "no mutations exist"
|
||||
@ -146,7 +148,7 @@ convertMutationSelectionSet
|
||||
|
||||
httpManager <- askHTTPManager
|
||||
let selSetArguments = getSelSetArgsFromRootField resolvedSelSet rootFieldName
|
||||
(dbStepInfo, dbModelInfoList) <- flip runReaderT queryTagsComment $ mkDBMutationPlan @b env httpManager logger userInfo stringifyNum sourceName sourceConfig noRelsDBAST reqHeaders maybeOperationName selSetArguments headerPrecedence
|
||||
(dbStepInfo, dbModelInfoList) <- flip runReaderT queryTagsComment $ mkDBMutationPlan @b env httpManager logger userInfo stringifyNum sourceName sourceConfig noRelsDBAST reqHeaders maybeOperationName selSetArguments headerPrecedence traceQueryStatus
|
||||
pure $ (ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins, dbModelInfoList)
|
||||
RFRemote (RemoteSchemaName rName) remoteField -> do
|
||||
RemoteSchemaRootField remoteSchemaInfo resultCustomizer resolvedRemoteField <- runVariableCache $ resolveRemoteField userInfo remoteField
|
||||
|
@ -39,7 +39,7 @@ import Hasura.RemoteSchema.Metadata.Base (RemoteSchemaName (..))
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Server.Init.Config (ResponseInternalErrorsConfig (..))
|
||||
import Hasura.Server.Prometheus (PrometheusMetrics (..))
|
||||
import Hasura.Server.Types (HeaderPrecedence, MonadGetPolicies, RequestId (..))
|
||||
import Hasura.Server.Types (HeaderPrecedence, MonadGetPolicies, RequestId (..), TraceQueryStatus)
|
||||
import Hasura.Services.Network
|
||||
import Hasura.Session
|
||||
import Hasura.Tracing (MonadTrace)
|
||||
@ -94,6 +94,7 @@ convertQuerySelSet ::
|
||||
Maybe G.Name ->
|
||||
ResponseInternalErrorsConfig ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m (ExecutionPlan, [QueryRootField UnpreparedValue], DirectiveMap, ParameterizedQueryHash, [ModelInfoPart])
|
||||
convertQuerySelSet
|
||||
env
|
||||
@ -112,7 +113,8 @@ convertQuerySelSet
|
||||
reqId
|
||||
maybeOperationName
|
||||
responseErrorsConfig
|
||||
headerPrecedence = do
|
||||
headerPrecedence
|
||||
traceQueryStatus = do
|
||||
-- 1. Parse the GraphQL query into the 'RootFieldMap' and a 'SelectionSet'
|
||||
(unpreparedQueries, normalizedDirectives, normalizedSelectionSet) <-
|
||||
Tracing.newSpan "Parse query IR" $ parseGraphQLQuery nullInNonNullableVariables gqlContext varDefs (GH._grVariables gqlUnparsed) directives fields
|
||||
@ -142,7 +144,7 @@ convertQuerySelSet
|
||||
queryTagsAttributes = encodeQueryTags $ QTQuery $ QueryMetadata mReqId maybeOperationName rootFieldName parameterizedQueryHash
|
||||
queryTagsComment = Tagged.untag $ createQueryTags @m queryTagsAttributes queryTagsConfig
|
||||
(noRelsDBAST, remoteJoins) = RJ.getRemoteJoinsQueryDB db
|
||||
(dbStepInfo, dbModelInfoList) <- flip runReaderT queryTagsComment $ mkDBQueryPlan @b userInfo sourceName sourceConfig noRelsDBAST reqHeaders maybeOperationName
|
||||
(dbStepInfo, dbModelInfoList) <- flip runReaderT queryTagsComment $ mkDBQueryPlan @b userInfo sourceName sourceConfig noRelsDBAST reqHeaders maybeOperationName traceQueryStatus
|
||||
pure $ (ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins, dbModelInfoList)
|
||||
RFRemote (RemoteSchemaName rName) rf -> do
|
||||
RemoteSchemaRootField remoteSchemaInfo resultCustomizer remoteField <- runVariableCache $ for rf $ resolveRemoteVariable userInfo
|
||||
|
@ -38,7 +38,7 @@ import Hasura.RQL.IR.ModelInformation (ModelInfoPart (..), ModelOperationType (M
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RemoteSchema.SchemaCache
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Server.Types (MonadGetPolicies, RequestId)
|
||||
import Hasura.Server.Types (MonadGetPolicies, RequestId, TraceQueryStatus)
|
||||
import Hasura.Services.Network
|
||||
import Hasura.Session
|
||||
import Hasura.Tracing qualified as Tracing
|
||||
@ -78,8 +78,9 @@ processRemoteJoins ::
|
||||
Maybe RemoteJoins ->
|
||||
GQLReqUnparsed ->
|
||||
Tracing.HttpPropagator ->
|
||||
TraceQueryStatus ->
|
||||
m (EncJSON, [ModelInfoPart])
|
||||
processRemoteJoins requestId logger agentLicenseKey env requestHeaders userInfo lhs maybeJoinTree gqlreq tracesPropagator =
|
||||
processRemoteJoins requestId logger agentLicenseKey env requestHeaders userInfo lhs maybeJoinTree gqlreq tracesPropagator traceQueryStatus =
|
||||
Tracing.newSpan "Process remote joins" $ forRemoteJoins maybeJoinTree (lhs, []) \joinTree -> do
|
||||
lhsParsed <-
|
||||
JO.eitherDecode (encJToLBS lhs)
|
||||
@ -93,6 +94,7 @@ processRemoteJoins requestId logger agentLicenseKey env requestHeaders userInfo
|
||||
joinTree
|
||||
requestHeaders
|
||||
(_unOperationName <$> _grOperationName gqlreq)
|
||||
traceQueryStatus
|
||||
pure $ (encJFromOrderedValue $ runIdentity jsonResult, (modelInfoList))
|
||||
where
|
||||
-- How to process a source join call over the network.
|
||||
@ -153,8 +155,9 @@ foldJoinTreeWith ::
|
||||
RemoteJoins ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
m (f JO.Value, [ModelInfoPart])
|
||||
foldJoinTreeWith callSource callRemoteSchema userInfo lhs joinTree reqHeaders operationName = do
|
||||
foldJoinTreeWith callSource callRemoteSchema userInfo lhs joinTree reqHeaders operationName traceQueryStatus = do
|
||||
(compositeValue, joins) <- collectJoinArguments (assignJoinIds joinTree) lhs
|
||||
(joinIndices) <- fmap catMaybes
|
||||
$ for joins
|
||||
@ -167,7 +170,7 @@ foldJoinTreeWith callSource callRemoteSchema userInfo lhs joinTree reqHeaders op
|
||||
let remoteSchemaModel = ModelInfoPart (toTxt $ _vrsdName remoteSchemaInfo) ModelTypeRemoteSchema Nothing Nothing (ModelOperationType G.OperationTypeQuery)
|
||||
pure $ (fmap (childJoinTree,) maybeJoinIndex, Just [remoteSchemaModel])
|
||||
RemoteJoinSource sourceJoin childJoinTree -> do
|
||||
maybeJoinIndex <- S.makeSourceJoinCall callSource userInfo sourceJoin _jalFieldName joinArguments reqHeaders operationName
|
||||
maybeJoinIndex <- S.makeSourceJoinCall callSource userInfo sourceJoin _jalFieldName joinArguments reqHeaders operationName traceQueryStatus
|
||||
pure $ (fmap (childJoinTree,) $ fst <$> maybeJoinIndex, snd <$> maybeJoinIndex)
|
||||
result <- for previousStep $ \((childJoinTree, joinIndex)) -> do
|
||||
forRemoteJoins childJoinTree (joinIndex, []) $ \childRemoteJoins -> do
|
||||
@ -180,6 +183,7 @@ foldJoinTreeWith callSource callRemoteSchema userInfo lhs joinTree reqHeaders op
|
||||
childRemoteJoins
|
||||
reqHeaders
|
||||
operationName
|
||||
traceQueryStatus
|
||||
pure $ ((IntMap.fromAscList $ zip (IntMap.keys joinIndex) results), modelInfo)
|
||||
pure $ fmap (\(iMap, newModelInfo) -> (iMap, newModelInfo <> fromMaybe [] modelInfo')) result
|
||||
let (key, (compositeValue')) = unzip (IntMap.toList joinIndices)
|
||||
|
@ -70,9 +70,10 @@ makeSourceJoinCall ::
|
||||
IntMap.IntMap JoinArgument ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
-- | The resulting join index (see 'buildJoinIndex') if any.
|
||||
m (Maybe (IntMap.IntMap AO.Value, [ModelInfoPart]))
|
||||
makeSourceJoinCall networkFunction userInfo remoteSourceJoin jaFieldName joinArguments reqHeaders operationName =
|
||||
makeSourceJoinCall networkFunction userInfo remoteSourceJoin jaFieldName joinArguments reqHeaders operationName traceQueryStatus =
|
||||
Tracing.newSpan ("Remote join to data source " <> sourceName <<> " for field " <>> jaFieldName) do
|
||||
-- step 1: create the SourceJoinCall
|
||||
-- maybeSourceCall <-
|
||||
@ -80,7 +81,7 @@ makeSourceJoinCall networkFunction userInfo remoteSourceJoin jaFieldName joinArg
|
||||
-- buildSourceJoinCall @b userInfo jaFieldName joinArguments sjc
|
||||
maybeSourceCall <-
|
||||
AB.dispatchAnyBackend @EB.BackendExecute remoteSourceJoin
|
||||
$ buildSourceJoinCall userInfo jaFieldName joinArguments reqHeaders operationName
|
||||
$ buildSourceJoinCall userInfo jaFieldName joinArguments reqHeaders operationName traceQueryStatus
|
||||
-- if there actually is a remote call:
|
||||
for maybeSourceCall \(sourceCall, modelInfoList) -> do
|
||||
-- step 2: send this call over the network
|
||||
@ -115,9 +116,10 @@ buildSourceJoinCall ::
|
||||
IntMap.IntMap JoinArgument ->
|
||||
[HTTP.Header] ->
|
||||
Maybe G.Name ->
|
||||
TraceQueryStatus ->
|
||||
RemoteSourceJoin b ->
|
||||
m (Maybe (AB.AnyBackend SourceJoinCall, [ModelInfoPart]))
|
||||
buildSourceJoinCall userInfo jaFieldName joinArguments reqHeaders operationName remoteSourceJoin = do
|
||||
buildSourceJoinCall userInfo jaFieldName joinArguments reqHeaders operationName traceQueryStatus remoteSourceJoin = do
|
||||
Tracing.newSpan "Resolve execution step for remote join field" do
|
||||
let rows =
|
||||
IntMap.toList joinArguments <&> \(argumentId, argument) ->
|
||||
@ -142,6 +144,7 @@ buildSourceJoinCall userInfo jaFieldName joinArguments reqHeaders operationName
|
||||
reqHeaders
|
||||
operationName
|
||||
(_rsjStringifyNum remoteSourceJoin)
|
||||
traceQueryStatus
|
||||
-- This should never fail, as field names in remote relationships are
|
||||
-- validated when building the schema cache.
|
||||
fieldName <-
|
||||
|
@ -95,7 +95,7 @@ import Hasura.Server.Prometheus
|
||||
recordGraphqlOperationMetric,
|
||||
)
|
||||
import Hasura.Server.Telemetry.Counters qualified as Telem
|
||||
import Hasura.Server.Types (HeaderPrecedence, ModelInfoLogState (..), MonadGetPolicies (..), ReadOnlyMode (..), RemoteSchemaResponsePriority (..), RequestId (..))
|
||||
import Hasura.Server.Types (HeaderPrecedence, ModelInfoLogState (..), MonadGetPolicies (..), ReadOnlyMode (..), RemoteSchemaResponsePriority (..), RequestId (..), TraceQueryStatus)
|
||||
import Hasura.Services
|
||||
import Hasura.Session (SessionVariable, SessionVariableValue, SessionVariables, UserInfo (..), filterSessionVariables)
|
||||
import Hasura.Tracing (MonadTrace, attachMetadata)
|
||||
@ -320,6 +320,7 @@ runGQ ::
|
||||
ReadOnlyMode ->
|
||||
RemoteSchemaResponsePriority ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
PrometheusMetrics ->
|
||||
L.Logger L.Hasura ->
|
||||
Maybe (CredentialCache AgentLicenseKey) ->
|
||||
@ -331,7 +332,7 @@ runGQ ::
|
||||
GQLReqUnparsed ->
|
||||
ResponseInternalErrorsConfig ->
|
||||
m (GQLQueryOperationSuccessLog, HttpResponse (Maybe GQResponse, EncJSON))
|
||||
runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence prometheusMetrics logger agentLicenseKey reqId userInfo ipAddress reqHeaders queryType reqUnparsed responseErrorsConfig = do
|
||||
runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence traceQueryStatus prometheusMetrics logger agentLicenseKey reqId userInfo ipAddress reqHeaders queryType reqUnparsed responseErrorsConfig = do
|
||||
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
|
||||
getModelInfoLogStatus' <- runGetModelInfoLogStatus
|
||||
modelInfoLogStatus <- liftIO getModelInfoLogStatus'
|
||||
@ -376,6 +377,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
|
||||
reqId
|
||||
responseErrorsConfig
|
||||
headerPrecedence
|
||||
traceQueryStatus
|
||||
|
||||
-- 4. Execute the execution plan producing a 'AnnotatedResponse'.
|
||||
(response, queryCachedStatus, modelInfoFromExecution) <- executePlan reqParsed runLimits execPlan
|
||||
@ -512,7 +514,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
|
||||
\(EB.DBStepInfo _ sourceConfig genSql tx resolvedConnectionTemplate :: EB.DBStepInfo b) ->
|
||||
runDBQuery @b reqId reqUnparsed fieldName userInfo logger agentLicenseKey sourceConfig (fmap (statsToAnyBackend @b) tx) genSql resolvedConnectionTemplate
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator traceQueryStatus
|
||||
pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse [], modelInfo)
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema
|
||||
@ -522,7 +524,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
|
||||
(time, resp, modelInfo) <- doQErr $ do
|
||||
(time, (resp, _)) <- EA.runActionExecution userInfo aep
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator traceQueryStatus
|
||||
pure (time, finalResponse, modelInfo)
|
||||
pure $ (AnnotatedResponsePart time Telem.Empty resp [], modelInfo)
|
||||
E.ExecStepRaw json -> do
|
||||
@ -546,7 +548,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
|
||||
\(EB.DBStepInfo _ sourceConfig genSql tx resolvedConnectionTemplate :: EB.DBStepInfo b) ->
|
||||
runDBMutation @b reqId reqUnparsed fieldName userInfo logger agentLicenseKey sourceConfig (fmap EB.arResult tx) genSql resolvedConnectionTemplate
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator traceQueryStatus
|
||||
pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse responseHeaders, modelInfo)
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema
|
||||
@ -556,7 +558,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
|
||||
(time, (resp, hdrs), modelInfo) <- doQErr $ do
|
||||
(time, (resp, hdrs)) <- EA.runActionExecution userInfo aep
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator
|
||||
RJ.processRemoteJoins reqId logger agentLicenseKey env reqHeaders userInfo resp remoteJoins reqUnparsed tracesPropagator traceQueryStatus
|
||||
pure (time, (finalResponse, hdrs), modelInfo)
|
||||
pure $ (AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs, modelInfo)
|
||||
E.ExecStepRaw json -> do
|
||||
@ -586,6 +588,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
|
||||
remoteJoins
|
||||
reqUnparsed
|
||||
tracesPropagator
|
||||
traceQueryStatus
|
||||
let filteredHeaders = filter ((== "Set-Cookie") . fst) remoteResponseHeaders
|
||||
pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Remote finalResponse filteredHeaders, modelInfo)
|
||||
|
||||
@ -809,6 +812,7 @@ runGQBatched ::
|
||||
ResponseInternalErrorsConfig ->
|
||||
RemoteSchemaResponsePriority ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
UserInfo ->
|
||||
Wai.IpAddress ->
|
||||
[HTTP.Header] ->
|
||||
@ -816,10 +820,10 @@ runGQBatched ::
|
||||
-- | the batched request with unparsed GraphQL query
|
||||
GQLBatchedReqs (GQLReq GQLQueryText) ->
|
||||
m (HttpLogGraphQLInfo, HttpResponse EncJSON)
|
||||
runGQBatched env sqlGenCtx sc enableAL readOnlyMode prometheusMetrics logger agentLicenseKey reqId responseErrorsConfig remoteSchemaResponsePriority headerPrecedence userInfo ipAddress reqHdrs queryType query =
|
||||
runGQBatched env sqlGenCtx sc enableAL readOnlyMode prometheusMetrics logger agentLicenseKey reqId responseErrorsConfig remoteSchemaResponsePriority headerPrecedence traceQueryStatus userInfo ipAddress reqHdrs queryType query =
|
||||
case query of
|
||||
GQLSingleRequest req -> do
|
||||
(gqlQueryOperationLog, httpResp) <- runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence prometheusMetrics logger agentLicenseKey reqId userInfo ipAddress reqHdrs queryType req responseErrorsConfig
|
||||
(gqlQueryOperationLog, httpResp) <- runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence traceQueryStatus prometheusMetrics logger agentLicenseKey reqId userInfo ipAddress reqHdrs queryType req responseErrorsConfig
|
||||
let httpLoggingGQInfo = (CommonHttpLogMetadata L.RequestModeSingle (Just (GQLSingleRequest (GQLQueryOperationSuccess gqlQueryOperationLog))), (PQHSetSingleton (gqolParameterizedQueryHash gqlQueryOperationLog)))
|
||||
pure (httpLoggingGQInfo, snd <$> httpResp)
|
||||
GQLBatchedReqs reqs -> do
|
||||
@ -832,7 +836,7 @@ runGQBatched env sqlGenCtx sc enableAL readOnlyMode prometheusMetrics logger age
|
||||
flip HttpResponse []
|
||||
. encJFromList
|
||||
. map (either (encJFromJEncoding . encodeGQErr includeInternal) _hrBody)
|
||||
responses <- for reqs \req -> fmap (req,) $ try $ (fmap . fmap . fmap) snd $ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence prometheusMetrics logger agentLicenseKey reqId userInfo ipAddress reqHdrs queryType req responseErrorsConfig
|
||||
responses <- for reqs \req -> fmap (req,) $ try $ (fmap . fmap . fmap) snd $ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence traceQueryStatus prometheusMetrics logger agentLicenseKey reqId userInfo ipAddress reqHdrs queryType req responseErrorsConfig
|
||||
let requestsOperationLogs = map fst $ rights $ map snd responses
|
||||
batchOperationLogs =
|
||||
map
|
||||
|
@ -98,9 +98,10 @@ createWSServerApp enabledLogTypes serverEnv connInitTimeout licenseKeyCache = \
|
||||
|
||||
onMessageHandler conn bs sp = do
|
||||
headerPrecedence <- liftIO $ acHeaderPrecedence <$> getAppContext (_wseAppStateRef serverEnv)
|
||||
traceQueryStatus <- liftIO $ acTraceQueryStatus <$> getAppContext (_wseAppStateRef serverEnv)
|
||||
responseErrorsConfig <- liftIO $ acResponseInternalErrorsConfig <$> getAppContext (_wseAppStateRef serverEnv)
|
||||
mask_
|
||||
$ onMessage enabledLogTypes getAuthMode serverEnv conn bs (wsActions sp) licenseKeyCache responseErrorsConfig headerPrecedence
|
||||
$ onMessage enabledLogTypes getAuthMode serverEnv conn bs (wsActions sp) licenseKeyCache responseErrorsConfig headerPrecedence traceQueryStatus
|
||||
|
||||
onCloseHandler conn = mask_ do
|
||||
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
|
||||
|
@ -105,7 +105,7 @@ import Hasura.Server.Prometheus
|
||||
recordGraphqlOperationMetric,
|
||||
)
|
||||
import Hasura.Server.Telemetry.Counters qualified as Telem
|
||||
import Hasura.Server.Types (GranularPrometheusMetricsState (..), HeaderPrecedence, ModelInfoLogState (..), MonadGetPolicies (..), RemoteSchemaResponsePriority, RequestId, getRequestId)
|
||||
import Hasura.Server.Types (GranularPrometheusMetricsState (..), HeaderPrecedence, ModelInfoLogState (..), MonadGetPolicies (..), RemoteSchemaResponsePriority, RequestId, TraceQueryStatus, getRequestId)
|
||||
import Hasura.Services.Network
|
||||
import Hasura.Session
|
||||
import Hasura.Tracing qualified as Tracing
|
||||
@ -449,8 +449,9 @@ onStart ::
|
||||
WS.WSActions WSConnData ->
|
||||
ResponseInternalErrorsConfig ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m ()
|
||||
onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables (StartMsg opId q) onMessageActions responseErrorsConfig headerPrecedence = catchAndIgnore $ do
|
||||
onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables (StartMsg opId q) onMessageActions responseErrorsConfig headerPrecedence traceQueryStatus = catchAndIgnore $ do
|
||||
modelInfoLogStatus' <- runGetModelInfoLogStatus
|
||||
modelInfoLogStatus <- liftIO modelInfoLogStatus'
|
||||
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
|
||||
@ -521,6 +522,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
|
||||
requestId
|
||||
responseErrorsConfig
|
||||
headerPrecedence
|
||||
traceQueryStatus
|
||||
|
||||
(parameterizedQueryHash, execPlan, modelInfoList) <- onLeft execPlanE (withComplete . preExecErr granularPrometheusMetricsState requestId (Just gqlOpType) opName Nothing)
|
||||
|
||||
@ -564,7 +566,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
|
||||
genSql
|
||||
resolvedConnectionTemplate
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator traceQueryStatus
|
||||
pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse [], modelInfo)
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema
|
||||
@ -574,7 +576,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
|
||||
(time, (resp, _), modelInfo) <- doQErr $ do
|
||||
(time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator traceQueryStatus
|
||||
pure (time, (finalResponse, hdrs), modelInfo)
|
||||
pure $ (AnnotatedResponsePart time Telem.Empty resp [], modelInfo)
|
||||
E.ExecStepRaw json -> do
|
||||
@ -648,14 +650,14 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
|
||||
genSql
|
||||
resolvedConnectionTemplate
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator traceQueryStatus
|
||||
pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse [], modelInfo)
|
||||
E.ExecStepAction actionExecPlan _ remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction
|
||||
(time, (resp, hdrs), modelInfo) <- doQErr $ do
|
||||
(time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan
|
||||
(finalResponse, modelInfo) <-
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator
|
||||
RJ.processRemoteJoins requestId logger agentLicenseKey env reqHdrs userInfo resp remoteJoins q tracesPropagator traceQueryStatus
|
||||
pure (time, (finalResponse, hdrs), modelInfo)
|
||||
pure $ (AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs, modelInfo)
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
@ -859,6 +861,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
|
||||
remoteJoins
|
||||
reqUnparsed
|
||||
tracesPropagator
|
||||
traceQueryStatus
|
||||
return $ (AnnotatedResponsePart telemTimeIO_DT Telem.Remote finalResponse [], modelInfo)
|
||||
|
||||
WSServerEnv
|
||||
@ -1113,8 +1116,9 @@ onMessage ::
|
||||
Maybe (CredentialCache AgentLicenseKey) ->
|
||||
ResponseInternalErrorsConfig ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
m ()
|
||||
onMessage enabledLogTypes authMode serverEnv wsConn msgRaw onMessageActions agentLicenseKey responseErrorsConfig headerPrecedence = do
|
||||
onMessage enabledLogTypes authMode serverEnv wsConn msgRaw onMessageActions agentLicenseKey responseErrorsConfig headerPrecedence traceQueryStatus = do
|
||||
Tracing.newTrace (_wseTraceSamplingPolicy serverEnv) "websocket" do
|
||||
case J.eitherDecode msgRaw of
|
||||
Left e -> do
|
||||
@ -1138,7 +1142,7 @@ onMessage enabledLogTypes authMode serverEnv wsConn msgRaw onMessageActions agen
|
||||
if _mcAnalyzeQueryVariables (scMetricsConfig schemaCache)
|
||||
then CaptureQueryVariables
|
||||
else DoNotCaptureQueryVariables
|
||||
onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables startMsg onMessageActions responseErrorsConfig headerPrecedence
|
||||
onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables startMsg onMessageActions responseErrorsConfig headerPrecedence traceQueryStatus
|
||||
CMStop stopMsg -> do
|
||||
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
|
||||
onStop serverEnv wsConn stopMsg granularPrometheusMetricsState
|
||||
|
@ -591,7 +591,7 @@ v1Alpha1GQHandler queryType query = do
|
||||
reqHeaders <- asks hcReqHeaders
|
||||
ipAddress <- asks hcSourceIpAddress
|
||||
requestId <- asks hcRequestId
|
||||
GH.runGQBatched acEnvironment acSQLGenCtx schemaCache acEnableAllowlist appEnvEnableReadOnlyMode appEnvPrometheusMetrics (_lsLogger appEnvLoggers) appEnvLicenseKeyCache requestId acResponseInternalErrorsConfig acRemoteSchemaResponsePriority acHeaderPrecedence userInfo ipAddress reqHeaders queryType query
|
||||
GH.runGQBatched acEnvironment acSQLGenCtx schemaCache acEnableAllowlist appEnvEnableReadOnlyMode appEnvPrometheusMetrics (_lsLogger appEnvLoggers) appEnvLicenseKeyCache requestId acResponseInternalErrorsConfig acRemoteSchemaResponsePriority acHeaderPrecedence acTraceQueryStatus userInfo ipAddress reqHeaders queryType query
|
||||
|
||||
v1GQHandler ::
|
||||
( MonadIO m,
|
||||
@ -960,7 +960,7 @@ httpApp setupHook appStateRef AppEnv {..} consoleType ekgStore closeWebsocketsOn
|
||||
Spock.PATCH -> pure EP.PATCH
|
||||
other -> throw400 BadRequest $ "Method " <> tshow other <> " not supported."
|
||||
_ -> throw400 BadRequest $ "Nonstandard method not allowed for REST endpoints"
|
||||
fmap JSONResp <$> runCustomEndpoint acEnvironment acSQLGenCtx schemaCache acEnableAllowlist appEnvEnableReadOnlyMode acRemoteSchemaResponsePriority acHeaderPrecedence appEnvPrometheusMetrics (_lsLogger appEnvLoggers) appEnvLicenseKeyCache requestId userInfo reqHeaders ipAddress req endpoints responseErrorsConfig
|
||||
fmap JSONResp <$> runCustomEndpoint acEnvironment acSQLGenCtx schemaCache acEnableAllowlist appEnvEnableReadOnlyMode acRemoteSchemaResponsePriority acHeaderPrecedence acTraceQueryStatus appEnvPrometheusMetrics (_lsLogger appEnvLoggers) appEnvLicenseKeyCache requestId userInfo reqHeaders ipAddress req endpoints responseErrorsConfig
|
||||
|
||||
-- See Issue #291 for discussion around restified feature
|
||||
Spock.hookRouteAll ("api" <//> "rest" <//> Spock.wildcard) $ \wildcard -> do
|
||||
|
@ -225,6 +225,7 @@ mkServeOptions sor@ServeOptionsRaw {..} = do
|
||||
soPersistedQueriesTtl <- withOptionDefault rsoPersistedQueriesTtl persistedQueriesTtlOption
|
||||
soRemoteSchemaResponsePriority <- withOptionDefault rsoRemoteSchemaResponsePriority remoteSchemaResponsePriorityOption
|
||||
soHeaderPrecedence <- withOptionDefault rsoHeaderPrecedence configuredHeaderPrecedenceOption
|
||||
soTraceQueryStatus <- withOptionDefault rsoTraceQueryStatus traceQueryStatusOption
|
||||
pure ServeOptions {..}
|
||||
|
||||
-- | Fetch Postgres 'Query.ConnParams' components from the environment
|
||||
|
@ -71,6 +71,7 @@ module Hasura.Server.Init.Arg.Command.Serve
|
||||
persistedQueriesTtlOption,
|
||||
remoteSchemaResponsePriorityOption,
|
||||
configuredHeaderPrecedenceOption,
|
||||
traceQueryStatusOption,
|
||||
|
||||
-- * Pretty Printer
|
||||
serveCmdFooter,
|
||||
@ -167,6 +168,7 @@ serveCommandParser =
|
||||
<*> parsePersistedQueriesTtl
|
||||
<*> parseRemoteSchemaResponsePriority
|
||||
<*> parseConfiguredHeaderPrecedence
|
||||
<*> parseTraceQueryStatus
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Serve Options
|
||||
@ -1341,6 +1343,14 @@ parseConfiguredHeaderPrecedence =
|
||||
<> Opt.help (Config._helpMessage configuredHeaderPrecedenceOption)
|
||||
)
|
||||
|
||||
parseTraceQueryStatus :: Opt.Parser (Maybe Types.TraceQueryStatus)
|
||||
parseTraceQueryStatus =
|
||||
(bool Nothing (Just Types.TraceQueryEnabled))
|
||||
<$> Opt.switch
|
||||
( Opt.long "trace-sql-query"
|
||||
<> Opt.help (Config._helpMessage traceQueryStatusOption)
|
||||
)
|
||||
|
||||
configuredHeaderPrecedenceOption :: Config.Option Types.HeaderPrecedence
|
||||
configuredHeaderPrecedenceOption =
|
||||
Config.Option
|
||||
@ -1351,6 +1361,15 @@ configuredHeaderPrecedenceOption =
|
||||
<> "when delivering payload to webhook for actions and input validations. (default: false)"
|
||||
}
|
||||
|
||||
traceQueryStatusOption :: Config.Option Types.TraceQueryStatus
|
||||
traceQueryStatusOption =
|
||||
Config.Option
|
||||
{ Config._default = Types.TraceQueryDisabled,
|
||||
Config._envVar = "HASURA_GRAPHQL_ENABLE_QUERY_TRACING",
|
||||
Config._helpMessage =
|
||||
"Enable query tracing for all queries. (default: false)"
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Pretty Printer
|
||||
|
||||
|
@ -332,7 +332,8 @@ data ServeOptionsRaw impl = ServeOptionsRaw
|
||||
rsoPersistedQueries :: Maybe Server.Types.PersistedQueriesState,
|
||||
rsoPersistedQueriesTtl :: Maybe Int,
|
||||
rsoRemoteSchemaResponsePriority :: Maybe Server.Types.RemoteSchemaResponsePriority,
|
||||
rsoHeaderPrecedence :: Maybe Server.Types.HeaderPrecedence
|
||||
rsoHeaderPrecedence :: Maybe Server.Types.HeaderPrecedence,
|
||||
rsoTraceQueryStatus :: Maybe Server.Types.TraceQueryStatus
|
||||
}
|
||||
|
||||
deriving stock instance (Show (Logging.EngineLogType impl)) => Show (ServeOptionsRaw impl)
|
||||
@ -643,7 +644,8 @@ data ServeOptions impl = ServeOptions
|
||||
soPersistedQueries :: Server.Types.PersistedQueriesState,
|
||||
soPersistedQueriesTtl :: Int,
|
||||
soRemoteSchemaResponsePriority :: Server.Types.RemoteSchemaResponsePriority,
|
||||
soHeaderPrecedence :: Server.Types.HeaderPrecedence
|
||||
soHeaderPrecedence :: Server.Types.HeaderPrecedence,
|
||||
soTraceQueryStatus :: Server.Types.TraceQueryStatus
|
||||
}
|
||||
|
||||
-- | 'ResponseInternalErrorsConfig' represents the encoding of the
|
||||
|
@ -393,3 +393,6 @@ instance FromEnv Server.Types.RemoteSchemaResponsePriority where
|
||||
|
||||
instance FromEnv Server.Types.HeaderPrecedence where
|
||||
fromEnv = fmap (bool Server.Types.ClientHeadersFirst Server.Types.ConfiguredHeadersFirst) . fromEnv @Bool
|
||||
|
||||
instance FromEnv Server.Types.TraceQueryStatus where
|
||||
fromEnv = fmap (bool Server.Types.TraceQueryDisabled Server.Types.TraceQueryEnabled) . fromEnv @Bool
|
||||
|
@ -120,6 +120,7 @@ runCustomEndpoint ::
|
||||
ReadOnlyMode ->
|
||||
RemoteSchemaResponsePriority ->
|
||||
HeaderPrecedence ->
|
||||
TraceQueryStatus ->
|
||||
PrometheusMetrics ->
|
||||
L.Logger L.Hasura ->
|
||||
Maybe (CredentialCache AgentLicenseKey) ->
|
||||
@ -131,7 +132,7 @@ runCustomEndpoint ::
|
||||
EndpointTrie GQLQueryWithText ->
|
||||
Init.ResponseInternalErrorsConfig ->
|
||||
m (HttpLogGraphQLInfo, HttpResponse EncJSON)
|
||||
runCustomEndpoint env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence prometheusMetrics logger agentLicenseKey requestId userInfo reqHeaders ipAddress RestRequest {..} endpoints responseErrorsConfig = do
|
||||
runCustomEndpoint env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence traceQueryStatus prometheusMetrics logger agentLicenseKey requestId userInfo reqHeaders ipAddress RestRequest {..} endpoints responseErrorsConfig = do
|
||||
-- First match the path to an endpoint.
|
||||
case matchPath reqMethod (T.split (== '/') reqPath) endpoints of
|
||||
MatchFound (queryx :: EndpointMetadata GQLQueryWithText) matches ->
|
||||
@ -161,7 +162,7 @@ runCustomEndpoint env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePri
|
||||
-- with the query string from the schema cache, and pass it
|
||||
-- through to the /v1/graphql endpoint.
|
||||
(httpLoggingMetadata, handlerResp) <- do
|
||||
(gqlOperationLog, resp) <- GH.runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence prometheusMetrics logger agentLicenseKey requestId userInfo ipAddress reqHeaders E.QueryHasura (mkPassthroughRequest queryx resolvedVariables) responseErrorsConfig
|
||||
(gqlOperationLog, resp) <- GH.runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority headerPrecedence traceQueryStatus prometheusMetrics logger agentLicenseKey requestId userInfo ipAddress reqHeaders E.QueryHasura (mkPassthroughRequest queryx resolvedVariables) responseErrorsConfig
|
||||
let httpLoggingGQInfo = (CommonHttpLogMetadata RequestModeNonBatchable Nothing, (PQHSetSingleton (gqolParameterizedQueryHash gqlOperationLog)))
|
||||
return (httpLoggingGQInfo, fst <$> resp)
|
||||
case sequence handlerResp of
|
||||
|
@ -33,6 +33,7 @@ module Hasura.Server.Types
|
||||
MonadGetPolicies (..),
|
||||
RemoteSchemaResponsePriority (..),
|
||||
HeaderPrecedence (..),
|
||||
TraceQueryStatus (..),
|
||||
)
|
||||
where
|
||||
|
||||
@ -398,3 +399,18 @@ instance ToJSON HeaderPrecedence where
|
||||
toJSON = \case
|
||||
ConfiguredHeadersFirst -> Bool True
|
||||
ClientHeadersFirst -> Bool False
|
||||
|
||||
data TraceQueryStatus
|
||||
= TraceQueryEnabled
|
||||
| TraceQueryDisabled
|
||||
deriving (Eq, Show, Generic)
|
||||
|
||||
instance FromJSON TraceQueryStatus where
|
||||
parseJSON = withBool "TraceQueryStatus" $ \case
|
||||
False -> pure TraceQueryDisabled
|
||||
True -> pure TraceQueryEnabled
|
||||
|
||||
instance ToJSON TraceQueryStatus where
|
||||
toJSON = \case
|
||||
TraceQueryDisabled -> Bool False
|
||||
TraceQueryEnabled -> Bool True
|
||||
|
@ -101,7 +101,8 @@ emptyServeOptionsRaw =
|
||||
rsoPersistedQueries = Nothing,
|
||||
rsoPersistedQueriesTtl = Nothing,
|
||||
rsoRemoteSchemaResponsePriority = Nothing,
|
||||
rsoHeaderPrecedence = Nothing
|
||||
rsoHeaderPrecedence = Nothing,
|
||||
rsoTraceQueryStatus = Nothing
|
||||
}
|
||||
|
||||
mkServeOptionsSpec :: Hspec.Spec
|
||||
|
@ -100,7 +100,8 @@ serveOptions =
|
||||
soPersistedQueries = Init._default Init.persistedQueriesOption,
|
||||
soPersistedQueriesTtl = Init._default Init.persistedQueriesTtlOption,
|
||||
soRemoteSchemaResponsePriority = Init._default Init.remoteSchemaResponsePriorityOption,
|
||||
soHeaderPrecedence = Init._default Init.configuredHeaderPrecedenceOption
|
||||
soHeaderPrecedence = Init._default Init.configuredHeaderPrecedenceOption,
|
||||
soTraceQueryStatus = Init._default Init.traceQueryStatusOption
|
||||
}
|
||||
|
||||
-- | What log level should be used by the engine; this is not exported, and
|
||||
|
Loading…
Reference in New Issue
Block a user