add postgres query to traces

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/10853
GitOrigin-RevId: b47c7077fc8fc7115ab05dffe93195abfeb4131d
This commit is contained in:
paritosh-08 2024-06-06 23:54:33 +05:30 committed by hasura-bot
parent 8bc5c01961
commit cf41d2abd9
25 changed files with 165 additions and 83 deletions

View File

@ -1229,6 +1229,19 @@ This sets transaction isolation.
| **Default** | `read-committed` | | **Default** | `read-committed` |
| **Supported in** | Deprecated in versions > `v2.0.0` | | **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 ### Unauthorized Role
This identifies an [unauthorized role](/auth/authentication/unauthenticated-access.mdx), used when the This identifies an [unauthorized role](/auth/authentication/unauthenticated-access.mdx), used when the

View File

@ -332,7 +332,8 @@ serveOptions =
soPersistedQueries = Init._default Init.persistedQueriesOption, soPersistedQueries = Init._default Init.persistedQueriesOption,
soPersistedQueriesTtl = Init._default Init.persistedQueriesTtlOption, soPersistedQueriesTtl = Init._default Init.persistedQueriesTtlOption,
soRemoteSchemaResponsePriority = Init._default Init.remoteSchemaResponsePriorityOption, 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 -- | What log level should be used by the engine; this is not exported, and

View File

@ -174,7 +174,8 @@ data AppContext = AppContext
acCloseWebsocketsOnMetadataChangeStatus :: CloseWebsocketsOnMetadataChangeStatus, acCloseWebsocketsOnMetadataChangeStatus :: CloseWebsocketsOnMetadataChangeStatus,
acSchemaSampledFeatureFlags :: SchemaSampledFeatureFlags, acSchemaSampledFeatureFlags :: SchemaSampledFeatureFlags,
acRemoteSchemaResponsePriority :: RemoteSchemaResponsePriority, acRemoteSchemaResponsePriority :: RemoteSchemaResponsePriority,
acHeaderPrecedence :: HeaderPrecedence acHeaderPrecedence :: HeaderPrecedence,
acTraceQueryStatus :: TraceQueryStatus
} }
-- | Collection of the LoggerCtx, the regular Logger and the PGLogger -- | Collection of the LoggerCtx, the regular Logger and the PGLogger
@ -297,7 +298,8 @@ buildAppContextRule = proc (ServeOptions {..}, env, _keys, checkFeatureFlag) ->
acCloseWebsocketsOnMetadataChangeStatus = soCloseWebsocketsOnMetadataChangeStatus, acCloseWebsocketsOnMetadataChangeStatus = soCloseWebsocketsOnMetadataChangeStatus,
acSchemaSampledFeatureFlags = schemaSampledFeatureFlags, acSchemaSampledFeatureFlags = schemaSampledFeatureFlags,
acRemoteSchemaResponsePriority = soRemoteSchemaResponsePriority, acRemoteSchemaResponsePriority = soRemoteSchemaResponsePriority,
acHeaderPrecedence = soHeaderPrecedence acHeaderPrecedence = soHeaderPrecedence,
acTraceQueryStatus = soTraceQueryStatus
} }
where where
buildEventEngineCtx = Inc.cache proc (httpPoolSize, fetchInterval, fetchBatchSize) -> do buildEventEngineCtx = Inc.cache proc (httpPoolSize, fetchInterval, fetchBatchSize) -> do

View File

@ -38,7 +38,7 @@ import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Schema.Options qualified as Options import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.SQL.AnyBackend qualified as AB import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Server.Types (HeaderPrecedence) import Hasura.Server.Types (HeaderPrecedence, TraceQueryStatus)
import Hasura.Session import Hasura.Session
import Language.GraphQL.Draft.Syntax qualified as G import Language.GraphQL.Draft.Syntax qualified as G
import Network.HTTP.Client as HTTP import Network.HTTP.Client as HTTP
@ -78,8 +78,9 @@ bqDBQueryPlan ::
QueryDB 'BigQuery Void (UnpreparedValue 'BigQuery) -> QueryDB 'BigQuery Void (UnpreparedValue 'BigQuery) ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
m (DBStepInfo 'BigQuery, [ModelInfoPart]) m (DBStepInfo 'BigQuery, [ModelInfoPart])
bqDBQueryPlan userInfo sourceName sourceConfig qrf _ _ = do bqDBQueryPlan userInfo sourceName sourceConfig qrf _ _ _ = do
-- TODO (naveen): Append query tags to the query -- TODO (naveen): Append query tags to the query
select <- planNoPlan (BigQuery.bigQuerySourceConfigToFromIrConfig sourceConfig) userInfo qrf select <- planNoPlan (BigQuery.bigQuerySourceConfigToFromIrConfig sourceConfig) userInfo qrf
let action = OnBaseMonad do let action = OnBaseMonad do
@ -147,8 +148,9 @@ bqDBMutationPlan ::
Maybe G.Name -> Maybe G.Name ->
Maybe (HashMap G.Name (G.Value G.Variable)) -> Maybe (HashMap G.Name (G.Value G.Variable)) ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (DBStepInfo 'BigQuery, [ModelInfoPart]) 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" throw500 "mutations are not supported in BigQuery; this should be unreachable"
-- explain -- explain
@ -230,9 +232,10 @@ bqDBRemoteRelationshipPlan ::
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
Options.StringifyNumbers -> Options.StringifyNumbers ->
TraceQueryStatus ->
m (DBStepInfo 'BigQuery, [ModelInfoPart]) m (DBStepInfo 'BigQuery, [ModelInfoPart])
bqDBRemoteRelationshipPlan userInfo sourceName sourceConfig lhs lhsSchema argumentId relationship reqHeaders operationName stringifyNumbers = do 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 (dbStepInfo, modelInfo) <- flip runReaderT emptyQueryTagsComment $ bqDBQueryPlan userInfo sourceName sourceConfig rootSelection reqHeaders operationName traceQueryStatus
pure (dbStepInfo, modelInfo) pure (dbStepInfo, modelInfo)
where where
coerceToColumn = BigQuery.ColumnName . getFieldNameTxt coerceToColumn = BigQuery.ColumnName . getFieldNameTxt

View File

@ -54,7 +54,7 @@ instance BackendExecute 'DataConnector where
type MultiplexedQuery 'DataConnector = Void type MultiplexedQuery 'DataConnector = Void
type ExecutionMonad 'DataConnector = AgentClientT 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 queryPlan@Plan {..} <- flip runReaderT (API._cScalarTypes $ _scCapabilities sourceConfig, _uiSession) $ Plan.mkQueryPlan ir
transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession) transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession)
modelNames <- irToModelInfoGen sourceName ModelSourceTypeDataConnector ir modelNames <- irToModelInfoGen sourceName ModelSourceTypeDataConnector ir
@ -84,7 +84,7 @@ instance BackendExecute 'DataConnector where
dbsiResolvedConnectionTemplate = () 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 (mutationPlan@Plan {..}, modelNames) <- flip runReaderT (API._cScalarTypes $ _scCapabilities sourceConfig, _uiSession) $ Plan.mkMutationPlan sourceName ModelSourceTypeDataConnector mutationDB
transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession) transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession)
let modelInfo = getModelInfoPartfromModelNames modelNames (ModelOperationType G.OperationTypeMutation) let modelInfo = getModelInfoPartfromModelNames modelNames (ModelOperationType G.OperationTypeMutation)
@ -105,7 +105,7 @@ instance BackendExecute 'DataConnector where
mkDBStreamingSubscriptionPlan _ _ _ _ _ _ = mkDBStreamingSubscriptionPlan _ _ _ _ _ _ =
throw400 NotSupported "mkLiveQuerySubscriptionPlan: not implemented for the Data Connector backend." 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 (remoteRelationshipPlan@Plan {..}, modelInfo) <- flip runReaderT (API._cScalarTypes $ _scCapabilities sourceConfig, _uiSession) $ Plan.mkRemoteRelationshipPlan sourceName sourceConfig joinIds joinIdsSchema argumentIdFieldName resultFieldName ir
transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession) transformedSourceConfig <- transformSourceConfig sourceConfig (Just _uiSession)
pure pure

View File

@ -55,7 +55,7 @@ import Hasura.RQL.Types.Column qualified as RQLColumn
import Hasura.RQL.Types.Common as RQLTypes import Hasura.RQL.Types.Common as RQLTypes
import Hasura.RQL.Types.Schema.Options qualified as Options import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.SQL.AnyBackend qualified as AB import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Server.Types (HeaderPrecedence) import Hasura.Server.Types (HeaderPrecedence, TraceQueryStatus)
import Hasura.Session import Hasura.Session
import Language.GraphQL.Draft.Syntax qualified as G import Language.GraphQL.Draft.Syntax qualified as G
import Network.HTTP.Client as HTTP import Network.HTTP.Client as HTTP
@ -100,8 +100,9 @@ msDBQueryPlan ::
QueryDB 'MSSQL Void (UnpreparedValue 'MSSQL) -> QueryDB 'MSSQL Void (UnpreparedValue 'MSSQL) ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
m (DBStepInfo 'MSSQL, [ModelInfoPart]) m (DBStepInfo 'MSSQL, [ModelInfoPart])
msDBQueryPlan userInfo sourceName sourceConfig qrf _ _ = do msDBQueryPlan userInfo sourceName sourceConfig qrf _ _ _ = do
let sessionVariables = _uiSession userInfo let sessionVariables = _uiSession userInfo
QueryWithDDL {qwdBeforeSteps, qwdAfterSteps, qwdQuery = statement} <- planQuery sessionVariables qrf QueryWithDDL {qwdBeforeSteps, qwdAfterSteps, qwdQuery = statement} <- planQuery sessionVariables qrf
queryTags <- ask queryTags <- ask
@ -319,8 +320,9 @@ msDBMutationPlan ::
Maybe G.Name -> Maybe G.Name ->
Maybe (HashMap G.Name (G.Value G.Variable)) -> Maybe (HashMap G.Name (G.Value G.Variable)) ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (DBStepInfo 'MSSQL, [ModelInfoPart]) 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 go <$> case mrf of
MDBInsert annInsert -> executeInsert userInfo stringifyNum sourceName ModelSourceTypeMSSQL sourceConfig annInsert MDBInsert annInsert -> executeInsert userInfo stringifyNum sourceName ModelSourceTypeMSSQL sourceConfig annInsert
MDBDelete annDelete -> executeDelete userInfo stringifyNum sourceName ModelSourceTypeMSSQL sourceConfig annDelete MDBDelete annDelete -> executeDelete userInfo stringifyNum sourceName ModelSourceTypeMSSQL sourceConfig annDelete
@ -525,8 +527,9 @@ msDBRemoteRelationshipPlan ::
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
Options.StringifyNumbers -> Options.StringifyNumbers ->
TraceQueryStatus ->
m (DBStepInfo 'MSSQL, [ModelInfoPart]) 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 -- `stringifyNumbers` is not currently handled in any SQL Server operation
statement <- planSourceRelationship (_uiSession userInfo) lhs lhsSchema argumentId relationship statement <- planSourceRelationship (_uiSession userInfo) lhs lhsSchema argumentId relationship

View File

@ -10,7 +10,6 @@
-- This module includes the Postgres implementation of queries, mutations, and more. -- This module includes the Postgres implementation of queries, mutations, and more.
module Hasura.Backends.Postgres.Instances.Execute module Hasura.Backends.Postgres.Instances.Execute
( PreparedSql (..), ( PreparedSql (..),
pgDBQueryPlanSimple,
) )
where where
@ -93,7 +92,7 @@ import Hasura.RQL.Types.Common (FieldName (..), JsonAggSelect (..), SourceName (
import Hasura.RQL.Types.Permission (ValidateInput (..), ValidateInputHttpDefinition (..)) import Hasura.RQL.Types.Permission (ValidateInput (..), ValidateInputHttpDefinition (..))
import Hasura.RQL.Types.Schema.Options qualified as Options import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.SQL.AnyBackend qualified as AB 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.Session (UserInfo (..))
import Hasura.Tracing qualified as Tracing import Hasura.Tracing qualified as Tracing
import Language.GraphQL.Draft.Syntax qualified as G import Language.GraphQL.Draft.Syntax qualified as G
@ -140,8 +139,9 @@ pgDBQueryPlan ::
QueryDB ('Postgres pgKind) Void (UnpreparedValue ('Postgres pgKind)) -> QueryDB ('Postgres pgKind) Void (UnpreparedValue ('Postgres pgKind)) ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
m ((DBStepInfo ('Postgres pgKind)), [ModelInfoPart]) 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}) <- (preparedQuery, PlanningSt {_psPrepped = planVals}) <-
flip runStateT initPlanningSt $ traverse (prepareWithPlan userInfo) qrf flip runStateT initPlanningSt $ traverse (prepareWithPlan userInfo) qrf
queryTagsComment <- ask queryTagsComment <- ask
@ -157,26 +157,9 @@ pgDBQueryPlan userInfo sourceName sourceConfig qrf reqHeaders operationName = do
modelNames <- irToModelInfoGen sourceName ModelSourceTypePostgres preparedQuery modelNames <- irToModelInfoGen sourceName ModelSourceTypePostgres preparedQuery
let modelInfo = getModelInfoPartfromModelNames modelNames (ModelOperationType G.OperationTypeQuery) let modelInfo = getModelInfoPartfromModelNames modelNames (ModelOperationType G.OperationTypeQuery)
let preparedSQLWithQueryTags = appendPreparedSQLWithQueryTags rootFieldPlan queryTagsComment 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) 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 :: pgDBQueryExplain ::
forall pgKind m. forall pgKind m.
( MonadError QErr m, ( MonadError QErr m,
@ -401,11 +384,12 @@ convertFunction ::
SourceName -> SourceName ->
ModelSourceType -> ModelSourceType ->
UserInfo -> UserInfo ->
TraceQueryStatus ->
JsonAggSelect -> JsonAggSelect ->
-- | VOLATILE function as 'SelectExp' -- | VOLATILE function as 'SelectExp'
IR.AnnSimpleSelectG ('Postgres pgKind) Void (UnpreparedValue ('Postgres pgKind)) -> IR.AnnSimpleSelectG ('Postgres pgKind) Void (UnpreparedValue ('Postgres pgKind)) ->
m (OnBaseMonad (PG.TxET QErr) EncJSON, [ModelNameInfo]) m (OnBaseMonad (PG.TxET QErr) EncJSON, [ModelNameInfo])
convertFunction sourceName modelSourceType userInfo jsonAggSelect unpreparedQuery = do convertFunction sourceName modelSourceType userInfo traceQueryStatus jsonAggSelect unpreparedQuery = do
queryTags <- ask queryTags <- ask
-- Transform the RQL AST into a prepared SQL query -- Transform the RQL AST into a prepared SQL query
(preparedQuery, PlanningSt {_psPrepped = planVals}) <- (preparedQuery, PlanningSt {_psPrepped = planVals}) <-
@ -419,7 +403,7 @@ convertFunction sourceName modelSourceType userInfo jsonAggSelect unpreparedQuer
modelNames <- irToModelInfoGen sourceName modelSourceType $ queryResultFn preparedQuery modelNames <- irToModelInfoGen sourceName modelSourceType $ queryResultFn preparedQuery
let preparedSQLWithQueryTags = appendPreparedSQLWithQueryTags rootFieldPlan queryTags let preparedSQLWithQueryTags = appendPreparedSQLWithQueryTags rootFieldPlan queryTags
pure pure
( fst (mkCurPlanTx userInfo preparedSQLWithQueryTags), -- forget (Maybe PreparedSql) ( fst (mkCurPlanTx userInfo preparedSQLWithQueryTags traceQueryStatus), -- forget (Maybe PreparedSql)
modelNames modelNames
) )
@ -444,8 +428,9 @@ pgDBMutationPlan ::
Maybe G.Name -> Maybe G.Name ->
Maybe (HashMap G.Name (G.Value G.Variable)) -> Maybe (HashMap G.Name (G.Value G.Variable)) ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (DBStepInfo ('Postgres pgKind), [ModelInfoPart]) 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 <- resolvedConnectionTemplate <-
let connectionTemplateResolver = let connectionTemplateResolver =
connectionTemplateConfigResolver (_pscConnectionTemplateConfig sourceConfig) 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 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 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 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 where
modelInfoList v = getModelInfoPartfromModelNames (snd v) (ModelOperationType G.OperationTypeMutation) modelInfoList v = getModelInfoPartfromModelNames (snd v) (ModelOperationType G.OperationTypeMutation)
go resolvedConnectionTemplate v = go resolvedConnectionTemplate v =
@ -647,8 +632,9 @@ testMultiplexedQueryTx (PGL.MultiplexedQuery query) cohortId cohortVariables = d
mkCurPlanTx :: mkCurPlanTx ::
UserInfo -> UserInfo ->
PreparedSql -> PreparedSql ->
TraceQueryStatus ->
(OnBaseMonad (PG.TxET QErr) EncJSON, Maybe PreparedSql) (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 -- generate the SQL and prepared vars or the bytestring
let args = withUserVars (_uiSession userInfo) prepMap let args = withUserVars (_uiSession userInfo) prepMap
-- WARNING: this quietly assumes the intmap keys are contiguous -- WARNING: this quietly assumes the intmap keys are contiguous
@ -656,6 +642,8 @@ mkCurPlanTx userInfo ps@(PreparedSql q prepMap) =
in (,Just ps) $ OnBaseMonad do in (,Just ps) $ OnBaseMonad do
-- https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/database/#connection-level-attributes -- https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/database/#connection-level-attributes
Tracing.attachMetadata [("db.system", "postgresql")] Tracing.attachMetadata [("db.system", "postgresql")]
when (traceQueryStatus == TraceQueryEnabled)
$ Tracing.attachMetadata [("db.query", PG.getQueryText q)]
runIdentity runIdentity
. PG.getRow . PG.getRow
<$> PG.rawQE dmlTxErrorHandler q prepArgs True <$> PG.rawQE dmlTxErrorHandler q prepArgs True
@ -724,14 +712,15 @@ pgDBRemoteRelationshipPlan ::
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
Options.StringifyNumbers -> Options.StringifyNumbers ->
TraceQueryStatus ->
m (DBStepInfo ('Postgres pgKind), [ModelInfoPart]) 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. -- 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 -- 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 -- metadata (e.g. 'ParameterizedQueryHash' doesn't make sense here) and find
-- a root field name that makes sense to attach to it. -- 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) pure (dbStepInfo, modelInfo)
where where
coerceToColumn = Postgres.unsafePGCol . getFieldNameTxt coerceToColumn = Postgres.unsafePGCol . getFieldNameTxt

View File

@ -63,7 +63,7 @@ import Hasura.RQL.Types.Subscription
import Hasura.SQL.AnyBackend qualified as AB import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Server.Init qualified as Init import Hasura.Server.Init qualified as Init
import Hasura.Server.Prometheus (PrometheusMetrics) 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.Services
import Hasura.Session (BackendOnlyFieldAccess (..), UserInfo (..)) import Hasura.Session (BackendOnlyFieldAccess (..), UserInfo (..))
import Hasura.Tracing qualified as Tracing import Hasura.Tracing qualified as Tracing
@ -364,6 +364,7 @@ getResolvedExecPlan ::
RequestId -> RequestId ->
Init.ResponseInternalErrorsConfig -> Init.ResponseInternalErrorsConfig ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (ParameterizedQueryHash, ResolvedExecutionPlan, [ModelInfoPart]) m (ParameterizedQueryHash, ResolvedExecutionPlan, [ModelInfoPart])
getResolvedExecPlan getResolvedExecPlan
env env
@ -380,7 +381,8 @@ getResolvedExecPlan
maybeOperationName maybeOperationName
reqId reqId
responseErrorsConfig responseErrorsConfig
headerPrecedence = do headerPrecedence
traceQueryStatus = do
let gCtx = makeGQLContext userInfo sc queryType let gCtx = makeGQLContext userInfo sc queryType
tracesPropagator = getOtelTracesPropagator $ scOpenTelemetryConfig sc tracesPropagator = getOtelTracesPropagator $ scOpenTelemetryConfig sc
@ -407,6 +409,7 @@ getResolvedExecPlan
maybeOperationName maybeOperationName
responseErrorsConfig responseErrorsConfig
headerPrecedence headerPrecedence
traceQueryStatus
Tracing.attachMetadata [("graphql.operation.type", "query"), ("parameterized_query_hash", bsToTxt $ unParamQueryHash parameterizedQueryHash)] Tracing.attachMetadata [("graphql.operation.type", "query"), ("parameterized_query_hash", bsToTxt $ unParamQueryHash parameterizedQueryHash)]
pure (parameterizedQueryHash, QueryExecutionPlan executionPlan queryRootFields dirMap, modelInfoList) pure (parameterizedQueryHash, QueryExecutionPlan executionPlan queryRootFields dirMap, modelInfoList)
G.TypedOperationDefinition G.OperationTypeMutation _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve mutation execution plan" $ do G.TypedOperationDefinition G.OperationTypeMutation _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve mutation execution plan" $ do
@ -430,6 +433,7 @@ getResolvedExecPlan
reqId reqId
maybeOperationName maybeOperationName
headerPrecedence headerPrecedence
traceQueryStatus
Tracing.attachMetadata [("graphql.operation.type", "mutation")] Tracing.attachMetadata [("graphql.operation.type", "mutation")]
pure (parameterizedQueryHash, MutationExecutionPlan executionPlan, modelInfoList) pure (parameterizedQueryHash, MutationExecutionPlan executionPlan, modelInfoList)
G.TypedOperationDefinition G.OperationTypeSubscription _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve subscription execution plan" $ do G.TypedOperationDefinition G.OperationTypeSubscription _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve subscription execution plan" $ do

View File

@ -82,6 +82,7 @@ class
QueryDB b Void (UnpreparedValue b) -> QueryDB b Void (UnpreparedValue b) ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
m ((DBStepInfo b), [ModelInfoPart]) m ((DBStepInfo b), [ModelInfoPart])
mkDBMutationPlan :: mkDBMutationPlan ::
forall m. forall m.
@ -103,6 +104,7 @@ class
Maybe G.Name -> Maybe G.Name ->
Maybe (HashMap G.Name (G.Value G.Variable)) -> Maybe (HashMap G.Name (G.Value G.Variable)) ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (DBStepInfo b, [ModelInfoPart]) m (DBStepInfo b, [ModelInfoPart])
mkLiveQuerySubscriptionPlan :: mkLiveQuerySubscriptionPlan ::
forall m. forall m.
@ -178,6 +180,7 @@ class
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
Options.StringifyNumbers -> Options.StringifyNumbers ->
TraceQueryStatus ->
m (DBStepInfo b, [ModelInfoPart]) m (DBStepInfo b, [ModelInfoPart])
-- | This is a helper function to convert a remote source's relationship to a -- | This is a helper function to convert a remote source's relationship to a

View File

@ -98,6 +98,7 @@ convertMutationSelectionSet ::
-- | Graphql Operation Name -- | Graphql Operation Name
Maybe G.Name -> Maybe G.Name ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (ExecutionPlan, ParameterizedQueryHash, [ModelInfoPart]) m (ExecutionPlan, ParameterizedQueryHash, [ModelInfoPart])
convertMutationSelectionSet convertMutationSelectionSet
env env
@ -115,7 +116,8 @@ convertMutationSelectionSet
introspectionDisabledRoles introspectionDisabledRoles
reqId reqId
maybeOperationName maybeOperationName
headerPrecedence = do headerPrecedence
traceQueryStatus = do
mutationParser <- mutationParser <-
onNothing (gqlMutationParser gqlContext) onNothing (gqlMutationParser gqlContext)
$ throw400 ValidationFailed "no mutations exist" $ throw400 ValidationFailed "no mutations exist"
@ -146,7 +148,7 @@ convertMutationSelectionSet
httpManager <- askHTTPManager httpManager <- askHTTPManager
let selSetArguments = getSelSetArgsFromRootField resolvedSelSet rootFieldName 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) pure $ (ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins, dbModelInfoList)
RFRemote (RemoteSchemaName rName) remoteField -> do RFRemote (RemoteSchemaName rName) remoteField -> do
RemoteSchemaRootField remoteSchemaInfo resultCustomizer resolvedRemoteField <- runVariableCache $ resolveRemoteField userInfo remoteField RemoteSchemaRootField remoteSchemaInfo resultCustomizer resolvedRemoteField <- runVariableCache $ resolveRemoteField userInfo remoteField

View File

@ -39,7 +39,7 @@ import Hasura.RemoteSchema.Metadata.Base (RemoteSchemaName (..))
import Hasura.SQL.AnyBackend qualified as AB import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Server.Init.Config (ResponseInternalErrorsConfig (..)) import Hasura.Server.Init.Config (ResponseInternalErrorsConfig (..))
import Hasura.Server.Prometheus (PrometheusMetrics (..)) 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.Services.Network
import Hasura.Session import Hasura.Session
import Hasura.Tracing (MonadTrace) import Hasura.Tracing (MonadTrace)
@ -94,6 +94,7 @@ convertQuerySelSet ::
Maybe G.Name -> Maybe G.Name ->
ResponseInternalErrorsConfig -> ResponseInternalErrorsConfig ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m (ExecutionPlan, [QueryRootField UnpreparedValue], DirectiveMap, ParameterizedQueryHash, [ModelInfoPart]) m (ExecutionPlan, [QueryRootField UnpreparedValue], DirectiveMap, ParameterizedQueryHash, [ModelInfoPart])
convertQuerySelSet convertQuerySelSet
env env
@ -112,7 +113,8 @@ convertQuerySelSet
reqId reqId
maybeOperationName maybeOperationName
responseErrorsConfig responseErrorsConfig
headerPrecedence = do headerPrecedence
traceQueryStatus = do
-- 1. Parse the GraphQL query into the 'RootFieldMap' and a 'SelectionSet' -- 1. Parse the GraphQL query into the 'RootFieldMap' and a 'SelectionSet'
(unpreparedQueries, normalizedDirectives, normalizedSelectionSet) <- (unpreparedQueries, normalizedDirectives, normalizedSelectionSet) <-
Tracing.newSpan "Parse query IR" $ parseGraphQLQuery nullInNonNullableVariables gqlContext varDefs (GH._grVariables gqlUnparsed) directives fields 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 queryTagsAttributes = encodeQueryTags $ QTQuery $ QueryMetadata mReqId maybeOperationName rootFieldName parameterizedQueryHash
queryTagsComment = Tagged.untag $ createQueryTags @m queryTagsAttributes queryTagsConfig queryTagsComment = Tagged.untag $ createQueryTags @m queryTagsAttributes queryTagsConfig
(noRelsDBAST, remoteJoins) = RJ.getRemoteJoinsQueryDB db (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) pure $ (ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins, dbModelInfoList)
RFRemote (RemoteSchemaName rName) rf -> do RFRemote (RemoteSchemaName rName) rf -> do
RemoteSchemaRootField remoteSchemaInfo resultCustomizer remoteField <- runVariableCache $ for rf $ resolveRemoteVariable userInfo RemoteSchemaRootField remoteSchemaInfo resultCustomizer remoteField <- runVariableCache $ for rf $ resolveRemoteVariable userInfo

View File

@ -38,7 +38,7 @@ import Hasura.RQL.IR.ModelInformation (ModelInfoPart (..), ModelOperationType (M
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RemoteSchema.SchemaCache import Hasura.RemoteSchema.SchemaCache
import Hasura.SQL.AnyBackend qualified as AB 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.Services.Network
import Hasura.Session import Hasura.Session
import Hasura.Tracing qualified as Tracing import Hasura.Tracing qualified as Tracing
@ -78,8 +78,9 @@ processRemoteJoins ::
Maybe RemoteJoins -> Maybe RemoteJoins ->
GQLReqUnparsed -> GQLReqUnparsed ->
Tracing.HttpPropagator -> Tracing.HttpPropagator ->
TraceQueryStatus ->
m (EncJSON, [ModelInfoPart]) 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 Tracing.newSpan "Process remote joins" $ forRemoteJoins maybeJoinTree (lhs, []) \joinTree -> do
lhsParsed <- lhsParsed <-
JO.eitherDecode (encJToLBS lhs) JO.eitherDecode (encJToLBS lhs)
@ -93,6 +94,7 @@ processRemoteJoins requestId logger agentLicenseKey env requestHeaders userInfo
joinTree joinTree
requestHeaders requestHeaders
(_unOperationName <$> _grOperationName gqlreq) (_unOperationName <$> _grOperationName gqlreq)
traceQueryStatus
pure $ (encJFromOrderedValue $ runIdentity jsonResult, (modelInfoList)) pure $ (encJFromOrderedValue $ runIdentity jsonResult, (modelInfoList))
where where
-- How to process a source join call over the network. -- How to process a source join call over the network.
@ -153,8 +155,9 @@ foldJoinTreeWith ::
RemoteJoins -> RemoteJoins ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
m (f JO.Value, [ModelInfoPart]) 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 (compositeValue, joins) <- collectJoinArguments (assignJoinIds joinTree) lhs
(joinIndices) <- fmap catMaybes (joinIndices) <- fmap catMaybes
$ for joins $ 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) let remoteSchemaModel = ModelInfoPart (toTxt $ _vrsdName remoteSchemaInfo) ModelTypeRemoteSchema Nothing Nothing (ModelOperationType G.OperationTypeQuery)
pure $ (fmap (childJoinTree,) maybeJoinIndex, Just [remoteSchemaModel]) pure $ (fmap (childJoinTree,) maybeJoinIndex, Just [remoteSchemaModel])
RemoteJoinSource sourceJoin childJoinTree -> do 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) pure $ (fmap (childJoinTree,) $ fst <$> maybeJoinIndex, snd <$> maybeJoinIndex)
result <- for previousStep $ \((childJoinTree, joinIndex)) -> do result <- for previousStep $ \((childJoinTree, joinIndex)) -> do
forRemoteJoins childJoinTree (joinIndex, []) $ \childRemoteJoins -> do forRemoteJoins childJoinTree (joinIndex, []) $ \childRemoteJoins -> do
@ -180,6 +183,7 @@ foldJoinTreeWith callSource callRemoteSchema userInfo lhs joinTree reqHeaders op
childRemoteJoins childRemoteJoins
reqHeaders reqHeaders
operationName operationName
traceQueryStatus
pure $ ((IntMap.fromAscList $ zip (IntMap.keys joinIndex) results), modelInfo) pure $ ((IntMap.fromAscList $ zip (IntMap.keys joinIndex) results), modelInfo)
pure $ fmap (\(iMap, newModelInfo) -> (iMap, newModelInfo <> fromMaybe [] modelInfo')) result pure $ fmap (\(iMap, newModelInfo) -> (iMap, newModelInfo <> fromMaybe [] modelInfo')) result
let (key, (compositeValue')) = unzip (IntMap.toList joinIndices) let (key, (compositeValue')) = unzip (IntMap.toList joinIndices)

View File

@ -70,9 +70,10 @@ makeSourceJoinCall ::
IntMap.IntMap JoinArgument -> IntMap.IntMap JoinArgument ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
-- | The resulting join index (see 'buildJoinIndex') if any. -- | The resulting join index (see 'buildJoinIndex') if any.
m (Maybe (IntMap.IntMap AO.Value, [ModelInfoPart])) 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 Tracing.newSpan ("Remote join to data source " <> sourceName <<> " for field " <>> jaFieldName) do
-- step 1: create the SourceJoinCall -- step 1: create the SourceJoinCall
-- maybeSourceCall <- -- maybeSourceCall <-
@ -80,7 +81,7 @@ makeSourceJoinCall networkFunction userInfo remoteSourceJoin jaFieldName joinArg
-- buildSourceJoinCall @b userInfo jaFieldName joinArguments sjc -- buildSourceJoinCall @b userInfo jaFieldName joinArguments sjc
maybeSourceCall <- maybeSourceCall <-
AB.dispatchAnyBackend @EB.BackendExecute remoteSourceJoin 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: -- if there actually is a remote call:
for maybeSourceCall \(sourceCall, modelInfoList) -> do for maybeSourceCall \(sourceCall, modelInfoList) -> do
-- step 2: send this call over the network -- step 2: send this call over the network
@ -115,9 +116,10 @@ buildSourceJoinCall ::
IntMap.IntMap JoinArgument -> IntMap.IntMap JoinArgument ->
[HTTP.Header] -> [HTTP.Header] ->
Maybe G.Name -> Maybe G.Name ->
TraceQueryStatus ->
RemoteSourceJoin b -> RemoteSourceJoin b ->
m (Maybe (AB.AnyBackend SourceJoinCall, [ModelInfoPart])) 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 Tracing.newSpan "Resolve execution step for remote join field" do
let rows = let rows =
IntMap.toList joinArguments <&> \(argumentId, argument) -> IntMap.toList joinArguments <&> \(argumentId, argument) ->
@ -142,6 +144,7 @@ buildSourceJoinCall userInfo jaFieldName joinArguments reqHeaders operationName
reqHeaders reqHeaders
operationName operationName
(_rsjStringifyNum remoteSourceJoin) (_rsjStringifyNum remoteSourceJoin)
traceQueryStatus
-- This should never fail, as field names in remote relationships are -- This should never fail, as field names in remote relationships are
-- validated when building the schema cache. -- validated when building the schema cache.
fieldName <- fieldName <-

View File

@ -95,7 +95,7 @@ import Hasura.Server.Prometheus
recordGraphqlOperationMetric, recordGraphqlOperationMetric,
) )
import Hasura.Server.Telemetry.Counters qualified as Telem 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.Services
import Hasura.Session (SessionVariable, SessionVariableValue, SessionVariables, UserInfo (..), filterSessionVariables) import Hasura.Session (SessionVariable, SessionVariableValue, SessionVariables, UserInfo (..), filterSessionVariables)
import Hasura.Tracing (MonadTrace, attachMetadata) import Hasura.Tracing (MonadTrace, attachMetadata)
@ -320,6 +320,7 @@ runGQ ::
ReadOnlyMode -> ReadOnlyMode ->
RemoteSchemaResponsePriority -> RemoteSchemaResponsePriority ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
PrometheusMetrics -> PrometheusMetrics ->
L.Logger L.Hasura -> L.Logger L.Hasura ->
Maybe (CredentialCache AgentLicenseKey) -> Maybe (CredentialCache AgentLicenseKey) ->
@ -331,7 +332,7 @@ runGQ ::
GQLReqUnparsed -> GQLReqUnparsed ->
ResponseInternalErrorsConfig -> ResponseInternalErrorsConfig ->
m (GQLQueryOperationSuccessLog, HttpResponse (Maybe GQResponse, EncJSON)) 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 granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
getModelInfoLogStatus' <- runGetModelInfoLogStatus getModelInfoLogStatus' <- runGetModelInfoLogStatus
modelInfoLogStatus <- liftIO getModelInfoLogStatus' modelInfoLogStatus <- liftIO getModelInfoLogStatus'
@ -376,6 +377,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
reqId reqId
responseErrorsConfig responseErrorsConfig
headerPrecedence headerPrecedence
traceQueryStatus
-- 4. Execute the execution plan producing a 'AnnotatedResponse'. -- 4. Execute the execution plan producing a 'AnnotatedResponse'.
(response, queryCachedStatus, modelInfoFromExecution) <- executePlan reqParsed runLimits execPlan (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) -> \(EB.DBStepInfo _ sourceConfig genSql tx resolvedConnectionTemplate :: EB.DBStepInfo b) ->
runDBQuery @b reqId reqUnparsed fieldName userInfo logger agentLicenseKey sourceConfig (fmap (statsToAnyBackend @b) tx) genSql resolvedConnectionTemplate runDBQuery @b reqId reqUnparsed fieldName userInfo logger agentLicenseKey sourceConfig (fmap (statsToAnyBackend @b) tx) genSql resolvedConnectionTemplate
(finalResponse, modelInfo) <- (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) pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse [], modelInfo)
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema 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, modelInfo) <- doQErr $ do
(time, (resp, _)) <- EA.runActionExecution userInfo aep (time, (resp, _)) <- EA.runActionExecution userInfo aep
(finalResponse, modelInfo) <- (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 (time, finalResponse, modelInfo)
pure $ (AnnotatedResponsePart time Telem.Empty resp [], modelInfo) pure $ (AnnotatedResponsePart time Telem.Empty resp [], modelInfo)
E.ExecStepRaw json -> do 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) -> \(EB.DBStepInfo _ sourceConfig genSql tx resolvedConnectionTemplate :: EB.DBStepInfo b) ->
runDBMutation @b reqId reqUnparsed fieldName userInfo logger agentLicenseKey sourceConfig (fmap EB.arResult tx) genSql resolvedConnectionTemplate runDBMutation @b reqId reqUnparsed fieldName userInfo logger agentLicenseKey sourceConfig (fmap EB.arResult tx) genSql resolvedConnectionTemplate
(finalResponse, modelInfo) <- (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) pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse responseHeaders, modelInfo)
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema 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), modelInfo) <- doQErr $ do
(time, (resp, hdrs)) <- EA.runActionExecution userInfo aep (time, (resp, hdrs)) <- EA.runActionExecution userInfo aep
(finalResponse, modelInfo) <- (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 (time, (finalResponse, hdrs), modelInfo)
pure $ (AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs, modelInfo) pure $ (AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs, modelInfo)
E.ExecStepRaw json -> do E.ExecStepRaw json -> do
@ -586,6 +588,7 @@ runGQ env sqlGenCtx sc enableAL readOnlyMode remoteSchemaResponsePriority header
remoteJoins remoteJoins
reqUnparsed reqUnparsed
tracesPropagator tracesPropagator
traceQueryStatus
let filteredHeaders = filter ((== "Set-Cookie") . fst) remoteResponseHeaders let filteredHeaders = filter ((== "Set-Cookie") . fst) remoteResponseHeaders
pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Remote finalResponse filteredHeaders, modelInfo) pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Remote finalResponse filteredHeaders, modelInfo)
@ -809,6 +812,7 @@ runGQBatched ::
ResponseInternalErrorsConfig -> ResponseInternalErrorsConfig ->
RemoteSchemaResponsePriority -> RemoteSchemaResponsePriority ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
UserInfo -> UserInfo ->
Wai.IpAddress -> Wai.IpAddress ->
[HTTP.Header] -> [HTTP.Header] ->
@ -816,10 +820,10 @@ runGQBatched ::
-- | the batched request with unparsed GraphQL query -- | the batched request with unparsed GraphQL query
GQLBatchedReqs (GQLReq GQLQueryText) -> GQLBatchedReqs (GQLReq GQLQueryText) ->
m (HttpLogGraphQLInfo, HttpResponse EncJSON) 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 case query of
GQLSingleRequest req -> do 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))) let httpLoggingGQInfo = (CommonHttpLogMetadata L.RequestModeSingle (Just (GQLSingleRequest (GQLQueryOperationSuccess gqlQueryOperationLog))), (PQHSetSingleton (gqolParameterizedQueryHash gqlQueryOperationLog)))
pure (httpLoggingGQInfo, snd <$> httpResp) pure (httpLoggingGQInfo, snd <$> httpResp)
GQLBatchedReqs reqs -> do GQLBatchedReqs reqs -> do
@ -832,7 +836,7 @@ runGQBatched env sqlGenCtx sc enableAL readOnlyMode prometheusMetrics logger age
flip HttpResponse [] flip HttpResponse []
. encJFromList . encJFromList
. map (either (encJFromJEncoding . encodeGQErr includeInternal) _hrBody) . 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 let requestsOperationLogs = map fst $ rights $ map snd responses
batchOperationLogs = batchOperationLogs =
map map

View File

@ -98,9 +98,10 @@ createWSServerApp enabledLogTypes serverEnv connInitTimeout licenseKeyCache = \
onMessageHandler conn bs sp = do onMessageHandler conn bs sp = do
headerPrecedence <- liftIO $ acHeaderPrecedence <$> getAppContext (_wseAppStateRef serverEnv) headerPrecedence <- liftIO $ acHeaderPrecedence <$> getAppContext (_wseAppStateRef serverEnv)
traceQueryStatus <- liftIO $ acTraceQueryStatus <$> getAppContext (_wseAppStateRef serverEnv)
responseErrorsConfig <- liftIO $ acResponseInternalErrorsConfig <$> getAppContext (_wseAppStateRef serverEnv) responseErrorsConfig <- liftIO $ acResponseInternalErrorsConfig <$> getAppContext (_wseAppStateRef serverEnv)
mask_ 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 onCloseHandler conn = mask_ do
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity

View File

@ -105,7 +105,7 @@ import Hasura.Server.Prometheus
recordGraphqlOperationMetric, recordGraphqlOperationMetric,
) )
import Hasura.Server.Telemetry.Counters qualified as Telem 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.Services.Network
import Hasura.Session import Hasura.Session
import Hasura.Tracing qualified as Tracing import Hasura.Tracing qualified as Tracing
@ -449,8 +449,9 @@ onStart ::
WS.WSActions WSConnData -> WS.WSActions WSConnData ->
ResponseInternalErrorsConfig -> ResponseInternalErrorsConfig ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m () 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' <- runGetModelInfoLogStatus
modelInfoLogStatus <- liftIO modelInfoLogStatus' modelInfoLogStatus <- liftIO modelInfoLogStatus'
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
@ -521,6 +522,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
requestId requestId
responseErrorsConfig responseErrorsConfig
headerPrecedence headerPrecedence
traceQueryStatus
(parameterizedQueryHash, execPlan, modelInfoList) <- onLeft execPlanE (withComplete . preExecErr granularPrometheusMetricsState requestId (Just gqlOpType) opName Nothing) (parameterizedQueryHash, execPlan, modelInfoList) <- onLeft execPlanE (withComplete . preExecErr granularPrometheusMetricsState requestId (Just gqlOpType) opName Nothing)
@ -564,7 +566,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
genSql genSql
resolvedConnectionTemplate resolvedConnectionTemplate
(finalResponse, modelInfo) <- (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) pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse [], modelInfo)
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema
@ -574,7 +576,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
(time, (resp, _), modelInfo) <- doQErr $ do (time, (resp, _), modelInfo) <- doQErr $ do
(time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan (time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan
(finalResponse, modelInfo) <- (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 (time, (finalResponse, hdrs), modelInfo)
pure $ (AnnotatedResponsePart time Telem.Empty resp [], modelInfo) pure $ (AnnotatedResponsePart time Telem.Empty resp [], modelInfo)
E.ExecStepRaw json -> do E.ExecStepRaw json -> do
@ -648,14 +650,14 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
genSql genSql
resolvedConnectionTemplate resolvedConnectionTemplate
(finalResponse, modelInfo) <- (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) pure $ (AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse [], modelInfo)
E.ExecStepAction actionExecPlan _ remoteJoins -> do E.ExecStepAction actionExecPlan _ remoteJoins -> do
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction
(time, (resp, hdrs), modelInfo) <- doQErr $ do (time, (resp, hdrs), modelInfo) <- doQErr $ do
(time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan (time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan
(finalResponse, modelInfo) <- (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 (time, (finalResponse, hdrs), modelInfo)
pure $ (AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs, modelInfo) pure $ (AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs, modelInfo)
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
@ -859,6 +861,7 @@ onStart enabledLogTypes agentLicenseKey serverEnv wsConn shouldCaptureVariables
remoteJoins remoteJoins
reqUnparsed reqUnparsed
tracesPropagator tracesPropagator
traceQueryStatus
return $ (AnnotatedResponsePart telemTimeIO_DT Telem.Remote finalResponse [], modelInfo) return $ (AnnotatedResponsePart telemTimeIO_DT Telem.Remote finalResponse [], modelInfo)
WSServerEnv WSServerEnv
@ -1113,8 +1116,9 @@ onMessage ::
Maybe (CredentialCache AgentLicenseKey) -> Maybe (CredentialCache AgentLicenseKey) ->
ResponseInternalErrorsConfig -> ResponseInternalErrorsConfig ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
m () 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 Tracing.newTrace (_wseTraceSamplingPolicy serverEnv) "websocket" do
case J.eitherDecode msgRaw of case J.eitherDecode msgRaw of
Left e -> do Left e -> do
@ -1138,7 +1142,7 @@ onMessage enabledLogTypes authMode serverEnv wsConn msgRaw onMessageActions agen
if _mcAnalyzeQueryVariables (scMetricsConfig schemaCache) if _mcAnalyzeQueryVariables (scMetricsConfig schemaCache)
then CaptureQueryVariables then CaptureQueryVariables
else DoNotCaptureQueryVariables 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 CMStop stopMsg -> do
granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity granularPrometheusMetricsState <- runGetPrometheusMetricsGranularity
onStop serverEnv wsConn stopMsg granularPrometheusMetricsState onStop serverEnv wsConn stopMsg granularPrometheusMetricsState

View File

@ -591,7 +591,7 @@ v1Alpha1GQHandler queryType query = do
reqHeaders <- asks hcReqHeaders reqHeaders <- asks hcReqHeaders
ipAddress <- asks hcSourceIpAddress ipAddress <- asks hcSourceIpAddress
requestId <- asks hcRequestId 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 :: v1GQHandler ::
( MonadIO m, ( MonadIO m,
@ -960,7 +960,7 @@ httpApp setupHook appStateRef AppEnv {..} consoleType ekgStore closeWebsocketsOn
Spock.PATCH -> pure EP.PATCH Spock.PATCH -> pure EP.PATCH
other -> throw400 BadRequest $ "Method " <> tshow other <> " not supported." other -> throw400 BadRequest $ "Method " <> tshow other <> " not supported."
_ -> throw400 BadRequest $ "Nonstandard method not allowed for REST endpoints" _ -> 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 -- See Issue #291 for discussion around restified feature
Spock.hookRouteAll ("api" <//> "rest" <//> Spock.wildcard) $ \wildcard -> do Spock.hookRouteAll ("api" <//> "rest" <//> Spock.wildcard) $ \wildcard -> do

View File

@ -225,6 +225,7 @@ mkServeOptions sor@ServeOptionsRaw {..} = do
soPersistedQueriesTtl <- withOptionDefault rsoPersistedQueriesTtl persistedQueriesTtlOption soPersistedQueriesTtl <- withOptionDefault rsoPersistedQueriesTtl persistedQueriesTtlOption
soRemoteSchemaResponsePriority <- withOptionDefault rsoRemoteSchemaResponsePriority remoteSchemaResponsePriorityOption soRemoteSchemaResponsePriority <- withOptionDefault rsoRemoteSchemaResponsePriority remoteSchemaResponsePriorityOption
soHeaderPrecedence <- withOptionDefault rsoHeaderPrecedence configuredHeaderPrecedenceOption soHeaderPrecedence <- withOptionDefault rsoHeaderPrecedence configuredHeaderPrecedenceOption
soTraceQueryStatus <- withOptionDefault rsoTraceQueryStatus traceQueryStatusOption
pure ServeOptions {..} pure ServeOptions {..}
-- | Fetch Postgres 'Query.ConnParams' components from the environment -- | Fetch Postgres 'Query.ConnParams' components from the environment

View File

@ -71,6 +71,7 @@ module Hasura.Server.Init.Arg.Command.Serve
persistedQueriesTtlOption, persistedQueriesTtlOption,
remoteSchemaResponsePriorityOption, remoteSchemaResponsePriorityOption,
configuredHeaderPrecedenceOption, configuredHeaderPrecedenceOption,
traceQueryStatusOption,
-- * Pretty Printer -- * Pretty Printer
serveCmdFooter, serveCmdFooter,
@ -167,6 +168,7 @@ serveCommandParser =
<*> parsePersistedQueriesTtl <*> parsePersistedQueriesTtl
<*> parseRemoteSchemaResponsePriority <*> parseRemoteSchemaResponsePriority
<*> parseConfiguredHeaderPrecedence <*> parseConfiguredHeaderPrecedence
<*> parseTraceQueryStatus
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Serve Options -- Serve Options
@ -1341,6 +1343,14 @@ parseConfiguredHeaderPrecedence =
<> Opt.help (Config._helpMessage configuredHeaderPrecedenceOption) <> 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 Types.HeaderPrecedence
configuredHeaderPrecedenceOption = configuredHeaderPrecedenceOption =
Config.Option Config.Option
@ -1351,6 +1361,15 @@ configuredHeaderPrecedenceOption =
<> "when delivering payload to webhook for actions and input validations. (default: false)" <> "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 -- Pretty Printer

View File

@ -332,7 +332,8 @@ data ServeOptionsRaw impl = ServeOptionsRaw
rsoPersistedQueries :: Maybe Server.Types.PersistedQueriesState, rsoPersistedQueries :: Maybe Server.Types.PersistedQueriesState,
rsoPersistedQueriesTtl :: Maybe Int, rsoPersistedQueriesTtl :: Maybe Int,
rsoRemoteSchemaResponsePriority :: Maybe Server.Types.RemoteSchemaResponsePriority, 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) deriving stock instance (Show (Logging.EngineLogType impl)) => Show (ServeOptionsRaw impl)
@ -643,7 +644,8 @@ data ServeOptions impl = ServeOptions
soPersistedQueries :: Server.Types.PersistedQueriesState, soPersistedQueries :: Server.Types.PersistedQueriesState,
soPersistedQueriesTtl :: Int, soPersistedQueriesTtl :: Int,
soRemoteSchemaResponsePriority :: Server.Types.RemoteSchemaResponsePriority, soRemoteSchemaResponsePriority :: Server.Types.RemoteSchemaResponsePriority,
soHeaderPrecedence :: Server.Types.HeaderPrecedence soHeaderPrecedence :: Server.Types.HeaderPrecedence,
soTraceQueryStatus :: Server.Types.TraceQueryStatus
} }
-- | 'ResponseInternalErrorsConfig' represents the encoding of the -- | 'ResponseInternalErrorsConfig' represents the encoding of the

View File

@ -393,3 +393,6 @@ instance FromEnv Server.Types.RemoteSchemaResponsePriority where
instance FromEnv Server.Types.HeaderPrecedence where instance FromEnv Server.Types.HeaderPrecedence where
fromEnv = fmap (bool Server.Types.ClientHeadersFirst Server.Types.ConfiguredHeadersFirst) . fromEnv @Bool 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

View File

@ -120,6 +120,7 @@ runCustomEndpoint ::
ReadOnlyMode -> ReadOnlyMode ->
RemoteSchemaResponsePriority -> RemoteSchemaResponsePriority ->
HeaderPrecedence -> HeaderPrecedence ->
TraceQueryStatus ->
PrometheusMetrics -> PrometheusMetrics ->
L.Logger L.Hasura -> L.Logger L.Hasura ->
Maybe (CredentialCache AgentLicenseKey) -> Maybe (CredentialCache AgentLicenseKey) ->
@ -131,7 +132,7 @@ runCustomEndpoint ::
EndpointTrie GQLQueryWithText -> EndpointTrie GQLQueryWithText ->
Init.ResponseInternalErrorsConfig -> Init.ResponseInternalErrorsConfig ->
m (HttpLogGraphQLInfo, HttpResponse EncJSON) 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. -- First match the path to an endpoint.
case matchPath reqMethod (T.split (== '/') reqPath) endpoints of case matchPath reqMethod (T.split (== '/') reqPath) endpoints of
MatchFound (queryx :: EndpointMetadata GQLQueryWithText) matches -> 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 -- with the query string from the schema cache, and pass it
-- through to the /v1/graphql endpoint. -- through to the /v1/graphql endpoint.
(httpLoggingMetadata, handlerResp) <- do (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))) let httpLoggingGQInfo = (CommonHttpLogMetadata RequestModeNonBatchable Nothing, (PQHSetSingleton (gqolParameterizedQueryHash gqlOperationLog)))
return (httpLoggingGQInfo, fst <$> resp) return (httpLoggingGQInfo, fst <$> resp)
case sequence handlerResp of case sequence handlerResp of

View File

@ -33,6 +33,7 @@ module Hasura.Server.Types
MonadGetPolicies (..), MonadGetPolicies (..),
RemoteSchemaResponsePriority (..), RemoteSchemaResponsePriority (..),
HeaderPrecedence (..), HeaderPrecedence (..),
TraceQueryStatus (..),
) )
where where
@ -398,3 +399,18 @@ instance ToJSON HeaderPrecedence where
toJSON = \case toJSON = \case
ConfiguredHeadersFirst -> Bool True ConfiguredHeadersFirst -> Bool True
ClientHeadersFirst -> Bool False 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

View File

@ -101,7 +101,8 @@ emptyServeOptionsRaw =
rsoPersistedQueries = Nothing, rsoPersistedQueries = Nothing,
rsoPersistedQueriesTtl = Nothing, rsoPersistedQueriesTtl = Nothing,
rsoRemoteSchemaResponsePriority = Nothing, rsoRemoteSchemaResponsePriority = Nothing,
rsoHeaderPrecedence = Nothing rsoHeaderPrecedence = Nothing,
rsoTraceQueryStatus = Nothing
} }
mkServeOptionsSpec :: Hspec.Spec mkServeOptionsSpec :: Hspec.Spec

View File

@ -100,7 +100,8 @@ serveOptions =
soPersistedQueries = Init._default Init.persistedQueriesOption, soPersistedQueries = Init._default Init.persistedQueriesOption,
soPersistedQueriesTtl = Init._default Init.persistedQueriesTtlOption, soPersistedQueriesTtl = Init._default Init.persistedQueriesTtlOption,
soRemoteSchemaResponsePriority = Init._default Init.remoteSchemaResponsePriorityOption, 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 -- | What log level should be used by the engine; this is not exported, and