mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
feature(server): make execution statistics available through logging
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8286 Co-authored-by: Daniel Harvey <4729125+danieljharvey@users.noreply.github.com> GitOrigin-RevId: 72de592c08778649693d8ff0a0555b16fb28c4bd
This commit is contained in:
parent
6ac06561e6
commit
2124fa0f08
@ -89,7 +89,7 @@ runSQL_ f (BigQueryRunSQL query source) = do
|
||||
Right recordSet ->
|
||||
pure
|
||||
( encJFromJValue
|
||||
(RunSQLRes "TuplesOk" (f recordSet))
|
||||
(RunSQLRes "TuplesOk" (f (snd recordSet)))
|
||||
)
|
||||
|
||||
recordSetAsHeaderAndRows :: Execute.RecordSet -> J.Value
|
||||
|
@ -15,6 +15,7 @@ module Hasura.Backends.BigQuery.Execute
|
||||
Execute,
|
||||
ExecuteProblem (..),
|
||||
FieldNameText (..),
|
||||
Job (..),
|
||||
OutputValue (..),
|
||||
RecordSet (..),
|
||||
ShowDetails (..),
|
||||
@ -246,23 +247,23 @@ bigQueryProjectUrl projectId =
|
||||
runExecute ::
|
||||
MonadIO m =>
|
||||
BigQuerySourceConfig ->
|
||||
Execute RecordSet ->
|
||||
m (Either ExecuteProblem RecordSet)
|
||||
Execute (BigQuery.Job, RecordSet) ->
|
||||
m (Either ExecuteProblem (BigQuery.Job, RecordSet))
|
||||
runExecute sourceConfig m =
|
||||
liftIO
|
||||
( runExceptT
|
||||
( runReaderT
|
||||
(unExecute (m >>= getFinalRecordSet))
|
||||
(unExecute (m >>= traverse getFinalRecordSet))
|
||||
(ExecuteReader {sourceConfig})
|
||||
)
|
||||
)
|
||||
|
||||
executeSelect :: Select -> Execute RecordSet
|
||||
executeSelect :: Select -> Execute (BigQuery.Job, RecordSet)
|
||||
executeSelect select = do
|
||||
conn <- asks (_scConnection . sourceConfig)
|
||||
recordSet <-
|
||||
(job, recordSet) <-
|
||||
streamBigQuery conn (selectToBigQuery select) >>= liftEither
|
||||
pure recordSet {wantedFields = selectFinalWantedFields select}
|
||||
pure (job, recordSet {wantedFields = selectFinalWantedFields select})
|
||||
|
||||
-- | This is needed to strip out unneeded fields (join keys) in the
|
||||
-- final query. This is a relic of the data loader approach. A later
|
||||
@ -384,7 +385,7 @@ valueToBigQueryJson = go
|
||||
-- response. Until that test has been done, we should consider this a
|
||||
-- preliminary implementation.
|
||||
streamBigQuery ::
|
||||
(MonadIO m) => BigQueryConnection -> BigQuery -> m (Either ExecuteProblem RecordSet)
|
||||
(MonadIO m) => BigQueryConnection -> BigQuery -> m (Either ExecuteProblem (BigQuery.Job, RecordSet))
|
||||
streamBigQuery conn bigquery = do
|
||||
jobResult <- runExceptT $ createQueryJob conn bigquery
|
||||
case jobResult of
|
||||
@ -407,7 +408,7 @@ streamBigQuery conn bigquery = do
|
||||
Just recordSet@RecordSet {rows} ->
|
||||
(recordSet {rows = rows <> rows'})
|
||||
case mpageToken' of
|
||||
Nothing -> pure (Right extendedRecordSet)
|
||||
Nothing -> pure (Right (job, extendedRecordSet))
|
||||
Just pageToken' ->
|
||||
loop (pure pageToken') (pure extendedRecordSet)
|
||||
Right JobIncomplete {} -> do
|
||||
@ -488,7 +489,7 @@ data Fetch = Fetch
|
||||
getJobResults ::
|
||||
(MonadIO m) =>
|
||||
BigQueryConnection ->
|
||||
Job ->
|
||||
BigQuery.Job ->
|
||||
Fetch ->
|
||||
m (Either ExecuteProblem JobResultsResponse)
|
||||
getJobResults conn Job {jobId, location} Fetch {pageToken} = runExceptT $ do
|
||||
@ -531,33 +532,6 @@ getJobResults conn Job {jobId, location} Fetch {pageToken} = runExceptT $ do
|
||||
--------------------------------------------------------------------------------
|
||||
-- Creating jobs
|
||||
|
||||
data Job = Job
|
||||
{ state :: Text,
|
||||
jobId :: Text,
|
||||
location :: Text
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
instance Aeson.FromJSON Job where
|
||||
parseJSON =
|
||||
Aeson.withObject
|
||||
"Job"
|
||||
( \o -> do
|
||||
kind <- o .: "kind"
|
||||
if kind == ("bigquery#job" :: Text)
|
||||
then do
|
||||
state <- do
|
||||
status <- o .: "status"
|
||||
status .: "state"
|
||||
(jobId, location) <- do
|
||||
ref <- o .: "jobReference"
|
||||
-- 'location' is needed in addition to 'jobId' to query a job's
|
||||
-- status
|
||||
(,) <$> ref .: "jobId" <*> ref .: "location"
|
||||
pure Job {state, jobId, location}
|
||||
else fail ("Invalid kind: " <> show kind)
|
||||
)
|
||||
|
||||
-- | Make a Request return `JSON`
|
||||
jsonRequestHeader :: Request -> Request
|
||||
jsonRequestHeader =
|
||||
|
@ -84,7 +84,7 @@ bqDBQueryPlan userInfo _env sourceName sourceConfig qrf _ _ = do
|
||||
(DataLoader.executeSelect select)
|
||||
case result of
|
||||
Left err -> throw500WithDetail (DataLoader.executeProblemMessage DataLoader.HideDetails err) $ Aeson.toJSON err
|
||||
Right recordSet -> pure $! recordSetToEncJSON (BigQuery.selectCardinality select) recordSet
|
||||
Right (job, recordSet) -> pure ActionResult {arStatistics = Just BigQuery.ExecutionStatistics {_esJob = job}, arResult = recordSetToEncJSON (BigQuery.selectCardinality select) recordSet}
|
||||
pure $ DBStepInfo @'BigQuery sourceName sourceConfig (Just (selectSQLTextForExplain select)) action ()
|
||||
|
||||
-- | Convert the dataloader's 'RecordSet' type to JSON.
|
||||
@ -161,11 +161,12 @@ bqDBQueryExplain fieldName userInfo sourceName sourceConfig qrf _ _ = do
|
||||
Nothing
|
||||
( OnBaseMonad $
|
||||
pure $
|
||||
encJFromJValue $
|
||||
ExplainPlan
|
||||
fieldName
|
||||
(Just $ textSQL)
|
||||
(Just $ T.lines $ textSQL)
|
||||
withNoStatistics $
|
||||
encJFromJValue $
|
||||
ExplainPlan
|
||||
fieldName
|
||||
(Just $ textSQL)
|
||||
(Just $ T.lines $ textSQL)
|
||||
)
|
||||
()
|
||||
|
||||
|
@ -9,10 +9,11 @@ import Hasura.Base.Error
|
||||
import Hasura.EncJSON
|
||||
import Hasura.GraphQL.Execute.Backend
|
||||
import Hasura.GraphQL.Logging
|
||||
( GeneratedQuery (..),
|
||||
( ExecutionStats (..),
|
||||
GeneratedQuery (..),
|
||||
MonadQueryLog (..),
|
||||
QueryLog (..),
|
||||
QueryLogKind (QueryLogKindDatabase),
|
||||
QueryLogKind (QueryLogKindDatabase, QueryLogKindDatabaseResponse),
|
||||
)
|
||||
import Hasura.GraphQL.Namespace (RootFieldAlias)
|
||||
import Hasura.GraphQL.Transport.Backend
|
||||
@ -20,6 +21,7 @@ import Hasura.GraphQL.Transport.HTTP.Protocol
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.SQL.AnyBackend (AnyBackend)
|
||||
import Hasura.SQL.Backend
|
||||
import Hasura.Server.Types (RequestId)
|
||||
import Hasura.Session
|
||||
@ -45,7 +47,7 @@ runQuery ::
|
||||
UserInfo ->
|
||||
L.Logger L.Hasura ->
|
||||
SourceConfig 'BigQuery ->
|
||||
OnBaseMonad IdentityT EncJSON ->
|
||||
OnBaseMonad IdentityT (Maybe (AnyBackend ExecutionStats), EncJSON) ->
|
||||
Maybe Text ->
|
||||
ResolvedConnectionTemplate 'BigQuery ->
|
||||
-- | Also return the time spent in the PG query; for telemetry.
|
||||
@ -53,8 +55,12 @@ runQuery ::
|
||||
runQuery reqId query fieldName _userInfo logger _sourceConfig tx genSql _ = do
|
||||
-- log the generated SQL and the graphql query
|
||||
-- FIXME: fix logging by making logQueryLog expect something backend agnostic!
|
||||
logQueryLog logger $ mkQueryLog query fieldName genSql reqId
|
||||
withElapsedTime $ run tx
|
||||
logQueryLog logger $ mkQueryLog (QueryLogKindDatabase Nothing) query fieldName genSql reqId Nothing
|
||||
(diffTime, (stats, result)) <- withElapsedTime $ run tx
|
||||
|
||||
logQueryLog logger $ mkQueryLog (QueryLogKindDatabaseResponse Nothing) query fieldName Nothing reqId stats
|
||||
|
||||
pure (diffTime, result)
|
||||
|
||||
runQueryExplain ::
|
||||
( MonadIO m,
|
||||
@ -64,7 +70,7 @@ runQueryExplain ::
|
||||
) =>
|
||||
DBStepInfo 'BigQuery ->
|
||||
m EncJSON
|
||||
runQueryExplain (DBStepInfo _ _ _ action _) = run action
|
||||
runQueryExplain (DBStepInfo _ _ _ action _) = fmap arResult (run action)
|
||||
|
||||
runMutation ::
|
||||
( MonadError QErr m
|
||||
@ -95,14 +101,15 @@ run ::
|
||||
m a
|
||||
run = runIdentityT . runOnBaseMonad
|
||||
|
||||
-- @QueryLogKindDatabase Nothing@ means that the backend doesn't support connection templates
|
||||
mkQueryLog ::
|
||||
QueryLogKind ->
|
||||
GQLReqUnparsed ->
|
||||
RootFieldAlias ->
|
||||
Maybe Text ->
|
||||
RequestId ->
|
||||
Maybe (AnyBackend ExecutionStats) ->
|
||||
QueryLog
|
||||
mkQueryLog gqlQuery fieldName preparedSql requestId =
|
||||
-- @QueryLogKindDatabase Nothing@ means that the backend doesn't support connection templates
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase Nothing)
|
||||
mkQueryLog _qlKind _qlQuery fieldName preparedSql _qlRequestId _qlStatistics = QueryLog {..}
|
||||
where
|
||||
generatedQuery = preparedSql <&> \qs -> GeneratedQuery qs J.Null
|
||||
_qlGeneratedSql = preparedSql <&> \query -> (fieldName, GeneratedQuery query J.Null)
|
||||
|
@ -37,6 +37,7 @@ instance Backend 'BigQuery where
|
||||
type FunctionArgumentExp 'BigQuery = BigQuery.ArgumentExp
|
||||
type ComputedFieldImplicitArguments 'BigQuery = BigQuery.ComputedFieldImplicitArguments
|
||||
type ComputedFieldReturn 'BigQuery = BigQuery.ComputedFieldReturn
|
||||
type ExecutionStatistics 'BigQuery = BigQuery.ExecutionStatistics
|
||||
|
||||
type XStreamingSubscription 'BigQuery = XDisable
|
||||
type XComputedField 'BigQuery = XEnable
|
||||
|
@ -15,6 +15,7 @@ module Hasura.Backends.BigQuery.Types
|
||||
Datetime (..),
|
||||
Decimal (..),
|
||||
EntityAlias (..),
|
||||
ExecutionStatistics (..),
|
||||
Expression (..),
|
||||
FieldName (..),
|
||||
FieldOrigin (..),
|
||||
@ -23,6 +24,7 @@ module Hasura.Backends.BigQuery.Types
|
||||
SelectFromFunction (..),
|
||||
Geography (Geography),
|
||||
Int64 (Int64),
|
||||
Job (..),
|
||||
Join (..),
|
||||
JoinProvenance (ArrayAggregateJoinProvenance, ArrayJoinProvenance, ObjectJoinProvenance, OrderByJoinProvenance),
|
||||
JoinSource (..),
|
||||
@ -94,11 +96,11 @@ import Hasura.Base.Error
|
||||
import Hasura.Base.ErrorValue qualified as ErrorValue
|
||||
import Hasura.Base.ToErrorValue
|
||||
import Hasura.Metadata.DTO.Placeholder (placeholderCodecViaJSON)
|
||||
import Hasura.Prelude
|
||||
import Hasura.Prelude hiding (state)
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.Types.Function (FunctionArgName)
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Language.Haskell.TH.Syntax
|
||||
import Language.Haskell.TH.Syntax hiding (location)
|
||||
import Text.ParserCombinators.ReadP (eof, readP_to_S)
|
||||
|
||||
data Select = Select
|
||||
@ -1115,3 +1117,46 @@ projectionAlias =
|
||||
EntityProjection a -> pure (aliasedAlias a)
|
||||
ArrayEntityProjection _ a -> pure (aliasedAlias a)
|
||||
WindowProjection a -> pure (aliasedAlias a)
|
||||
|
||||
data Job = Job
|
||||
{ state :: Text,
|
||||
jobId :: Text,
|
||||
location :: Text
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
instance FromJSON Job where
|
||||
parseJSON =
|
||||
J.withObject
|
||||
"Job"
|
||||
( \o -> do
|
||||
kind <- o J..: "kind"
|
||||
if kind == ("bigquery#job" :: Text)
|
||||
then do
|
||||
state <- do
|
||||
status <- o J..: "status"
|
||||
status J..: "state"
|
||||
(jobId, location) <- do
|
||||
ref <- o J..: "jobReference"
|
||||
-- 'location' is needed in addition to 'jobId' to query a job's
|
||||
-- status
|
||||
(,) <$> ref J..: "jobId" <*> ref J..: "location"
|
||||
pure Job {state, jobId, location}
|
||||
else fail ("Invalid kind: " <> show kind)
|
||||
)
|
||||
|
||||
instance ToJSON Job where
|
||||
toJSON Job {..} =
|
||||
J.object
|
||||
[ "id" J..= jobId,
|
||||
"location" J..= location,
|
||||
"state" J..= state
|
||||
]
|
||||
|
||||
data ExecutionStatistics = ExecutionStatistics
|
||||
{ _esJob :: Job
|
||||
}
|
||||
deriving stock (Generic)
|
||||
|
||||
instance ToJSON ExecutionStatistics where
|
||||
toJSON = J.genericToJSON hasuraJSON
|
||||
|
@ -24,7 +24,7 @@ import Hasura.Backends.DataConnector.Plan.QueryPlan qualified as Plan
|
||||
import Hasura.Backends.DataConnector.Plan.RemoteRelationshipPlan qualified as Plan
|
||||
import Hasura.Base.Error (Code (..), QErr, throw400, throw400WithDetail)
|
||||
import Hasura.EncJSON (EncJSON, encJFromBuilder, encJFromJValue)
|
||||
import Hasura.GraphQL.Execute.Backend (BackendExecute (..), DBStepInfo (..), ExplainPlan (..), OnBaseMonad (..))
|
||||
import Hasura.GraphQL.Execute.Backend (BackendExecute (..), DBStepInfo (..), ExplainPlan (..), OnBaseMonad (..), withNoStatistics)
|
||||
import Hasura.GraphQL.Namespace qualified as GQL
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Common qualified as RQL
|
||||
@ -63,7 +63,7 @@ instance BackendExecute 'DataConnector where
|
||||
{ dbsiSourceName = sourceName,
|
||||
dbsiSourceConfig = transformedSourceConfig,
|
||||
dbsiPreparedQuery = Just $ QueryRequest _pRequest,
|
||||
dbsiAction = OnBaseMonad $ buildQueryAction sourceName transformedSourceConfig queryPlan,
|
||||
dbsiAction = OnBaseMonad $ fmap withNoStatistics (buildQueryAction sourceName transformedSourceConfig queryPlan),
|
||||
dbsiResolvedConnectionTemplate = ()
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ instance BackendExecute 'DataConnector where
|
||||
{ dbsiSourceName = sourceName,
|
||||
dbsiSourceConfig = transformedSourceConfig,
|
||||
dbsiPreparedQuery = Just $ QueryRequest _pRequest,
|
||||
dbsiAction = OnBaseMonad $ buildExplainAction fieldName sourceName transformedSourceConfig queryPlan,
|
||||
dbsiAction = OnBaseMonad $ fmap withNoStatistics (buildExplainAction fieldName sourceName transformedSourceConfig queryPlan),
|
||||
dbsiResolvedConnectionTemplate = ()
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ instance BackendExecute 'DataConnector where
|
||||
{ dbsiSourceName = sourceName,
|
||||
dbsiSourceConfig = transformedSourceConfig,
|
||||
dbsiPreparedQuery = Just $ MutationRequest _pRequest,
|
||||
dbsiAction = OnBaseMonad $ buildMutationAction sourceName transformedSourceConfig mutationPlan,
|
||||
dbsiAction = OnBaseMonad $ fmap withNoStatistics (buildMutationAction sourceName transformedSourceConfig mutationPlan),
|
||||
dbsiResolvedConnectionTemplate = ()
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ instance BackendExecute 'DataConnector where
|
||||
{ dbsiSourceName = sourceName,
|
||||
dbsiSourceConfig = transformedSourceConfig,
|
||||
dbsiPreparedQuery = Just $ QueryRequest _pRequest,
|
||||
dbsiAction = OnBaseMonad $ buildQueryAction sourceName transformedSourceConfig remoteRelationshipPlan,
|
||||
dbsiAction = OnBaseMonad $ fmap withNoStatistics (buildQueryAction sourceName transformedSourceConfig remoteRelationshipPlan),
|
||||
dbsiResolvedConnectionTemplate = ()
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import Hasura.Backends.DataConnector.Adapter.Types (SourceConfig (..))
|
||||
import Hasura.Backends.DataConnector.Agent.Client (AgentClientContext (..), AgentClientT, runAgentClientT)
|
||||
import Hasura.Base.Error (QErr)
|
||||
import Hasura.EncJSON (EncJSON)
|
||||
import Hasura.GraphQL.Execute.Backend (DBStepInfo (..), OnBaseMonad (..))
|
||||
import Hasura.GraphQL.Execute.Backend (DBStepInfo (..), OnBaseMonad (..), arResult)
|
||||
import Hasura.GraphQL.Logging qualified as HGL
|
||||
import Hasura.GraphQL.Namespace (RootFieldAlias)
|
||||
import Hasura.GraphQL.Transport.Backend (BackendTransport (..))
|
||||
@ -21,6 +21,7 @@ import Hasura.GraphQL.Transport.HTTP.Protocol (GQLReqUnparsed)
|
||||
import Hasura.Logging (Hasura, Logger, nullLogger)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (ResolvedConnectionTemplate)
|
||||
import Hasura.SQL.AnyBackend (AnyBackend)
|
||||
import Hasura.SQL.Backend (BackendType (DataConnector))
|
||||
import Hasura.Server.Types (RequestId)
|
||||
import Hasura.Session (UserInfo)
|
||||
@ -50,7 +51,7 @@ runDBQuery' ::
|
||||
UserInfo ->
|
||||
Logger Hasura ->
|
||||
SourceConfig ->
|
||||
OnBaseMonad AgentClientT a ->
|
||||
OnBaseMonad AgentClientT (Maybe (AnyBackend HGL.ExecutionStats), a) ->
|
||||
Maybe DataConnectorPreparedQuery ->
|
||||
ResolvedConnectionTemplate 'DataConnector ->
|
||||
m (DiffTime, a)
|
||||
@ -59,6 +60,7 @@ runDBQuery' requestId query fieldName _userInfo logger SourceConfig {..} action
|
||||
withElapsedTime
|
||||
. Tracing.newSpan ("Data Connector backend query for root field " <>> fieldName)
|
||||
. flip runAgentClientT (AgentClientContext logger _scEndpoint _scManager _scTimeoutMicroseconds)
|
||||
. fmap snd
|
||||
. runOnBaseMonad
|
||||
$ action
|
||||
|
||||
@ -75,6 +77,7 @@ mkQueryLog gqlQuery fieldName maybeQuery requestId =
|
||||
requestId
|
||||
-- @QueryLogKindDatabase Nothing@ means that the backend doesn't support connection templates
|
||||
(HGL.QueryLogKindDatabase Nothing)
|
||||
Nothing
|
||||
|
||||
runDBQueryExplain' ::
|
||||
( MonadIO m,
|
||||
@ -86,7 +89,7 @@ runDBQueryExplain' ::
|
||||
m EncJSON
|
||||
runDBQueryExplain' (DBStepInfo _ SourceConfig {..} _ action _) =
|
||||
flip runAgentClientT (AgentClientContext nullLogger _scEndpoint _scManager _scTimeoutMicroseconds) $
|
||||
runOnBaseMonad action
|
||||
fmap arResult (runOnBaseMonad action)
|
||||
|
||||
runDBMutation' ::
|
||||
( MonadIO m,
|
||||
|
@ -107,7 +107,7 @@ msDBQueryPlan userInfo _env sourceName sourceConfig qrf _ _ = do
|
||||
where
|
||||
runSelectQuery queryPrinter = OnBaseMonad do
|
||||
let queryTx = encJFromText <$> Tx.singleRowQueryE defaultMSSQLTxErrorHandler (toQueryFlat queryPrinter)
|
||||
mssqlRunReadOnly (_mscExecCtx sourceConfig) queryTx
|
||||
mssqlRunReadOnly (_mscExecCtx sourceConfig) (fmap withNoStatistics queryTx)
|
||||
|
||||
runShowplan ::
|
||||
MonadIO m =>
|
||||
@ -141,13 +141,13 @@ msDBQueryExplain fieldName userInfo sourceName sourceConfig qrf _ _ = do
|
||||
(_mscExecCtx sourceConfig)
|
||||
do
|
||||
showplan <- runShowplan query
|
||||
pure
|
||||
( encJFromJValue $
|
||||
pure $
|
||||
withNoStatistics $
|
||||
encJFromJValue $
|
||||
ExplainPlan
|
||||
fieldName
|
||||
(Just queryString)
|
||||
(Just showplan)
|
||||
)
|
||||
pure $
|
||||
AB.mkAnyBackend $
|
||||
DBStepInfo @'MSSQL sourceName sourceConfig Nothing odbcQuery ()
|
||||
@ -260,7 +260,7 @@ msDBMutationPlan userInfo _environment stringifyNum sourceName sourceConfig mrf
|
||||
MDBUpdate annUpdate -> executeUpdate userInfo stringifyNum sourceConfig annUpdate
|
||||
MDBFunction {} -> throw400 NotSupported "function mutations are not supported in MSSQL"
|
||||
where
|
||||
go v = DBStepInfo @'MSSQL sourceName sourceConfig Nothing v ()
|
||||
go v = DBStepInfo @'MSSQL sourceName sourceConfig Nothing (fmap withNoStatistics v) ()
|
||||
|
||||
-- * Subscription
|
||||
|
||||
@ -459,4 +459,4 @@ msDBRemoteRelationshipPlan _env userInfo sourceName sourceConfig lhs lhsSchema a
|
||||
where
|
||||
runSelectQuery queryPrinter = OnBaseMonad do
|
||||
let queryTx = encJFromText <$> Tx.singleRowQueryE defaultMSSQLTxErrorHandler (toQueryFlat queryPrinter)
|
||||
mssqlRunReadOnly (_mscExecCtx sourceConfig) queryTx
|
||||
mssqlRunReadOnly (_mscExecCtx sourceConfig) (fmap withNoStatistics queryTx)
|
||||
|
@ -32,6 +32,7 @@ import Hasura.GraphQL.Transport.HTTP.Protocol
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.SQL.AnyBackend (AnyBackend)
|
||||
import Hasura.SQL.Backend
|
||||
import Hasura.Server.Types (RequestId)
|
||||
import Hasura.Session
|
||||
@ -66,7 +67,7 @@ runQuery ::
|
||||
UserInfo ->
|
||||
L.Logger L.Hasura ->
|
||||
SourceConfig 'MSSQL ->
|
||||
OnBaseMonad (ExceptT QErr) EncJSON ->
|
||||
OnBaseMonad (ExceptT QErr) (Maybe (AnyBackend ExecutionStats), EncJSON) ->
|
||||
Maybe (PreparedQuery 'MSSQL) ->
|
||||
ResolvedConnectionTemplate 'MSSQL ->
|
||||
-- | Also return the time spent in the PG query; for telemetry.
|
||||
@ -75,7 +76,7 @@ runQuery reqId query fieldName _userInfo logger _sourceConfig tx genSql _ = do
|
||||
logQueryLog logger $ mkQueryLog query fieldName genSql reqId
|
||||
withElapsedTime $
|
||||
newSpan ("MSSQL Query for root field " <>> fieldName) $
|
||||
run tx
|
||||
fmap snd (run tx)
|
||||
|
||||
runQueryExplain ::
|
||||
( MonadIO m,
|
||||
@ -85,7 +86,7 @@ runQueryExplain ::
|
||||
) =>
|
||||
DBStepInfo 'MSSQL ->
|
||||
m EncJSON
|
||||
runQueryExplain (DBStepInfo _ _ _ action _) = run action
|
||||
runQueryExplain (DBStepInfo _ _ _ action _) = fmap arResult (run action)
|
||||
|
||||
runMutation ::
|
||||
( MonadIO m,
|
||||
@ -157,7 +158,7 @@ mkQueryLog ::
|
||||
QueryLog
|
||||
mkQueryLog gqlQuery fieldName preparedSql requestId =
|
||||
-- @QueryLogKindDatabase Nothing@ means that the backend doesn't support connection templates
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase Nothing)
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase Nothing) Nothing
|
||||
where
|
||||
generatedQuery =
|
||||
preparedSql <&> \queryString ->
|
||||
|
@ -73,7 +73,7 @@ mysqlDBQueryPlan userInfo _env sourceName sourceConfig qrf _ _ = do
|
||||
(DataLoader.execute actionsForest)
|
||||
either
|
||||
(throw500WithDetail "MySQL DataLoader Error" . toJSON . show)
|
||||
(pure . encJFromRecordSet)
|
||||
(pure . withNoStatistics . encJFromRecordSet)
|
||||
result
|
||||
)
|
||||
()
|
||||
@ -105,7 +105,7 @@ mysqlDBQueryExplain fieldName userInfo sourceName sourceConfig qrf _ _ = do
|
||||
fields <- fetchFields result
|
||||
rows <- fetchAllRows result
|
||||
let texts = concat $ parseTextRows fields rows
|
||||
pure $ encJFromJValue $ ExplainPlan fieldName (Just sqlQueryText) (Just texts)
|
||||
pure $ withNoStatistics $ encJFromJValue $ ExplainPlan fieldName (Just sqlQueryText) (Just texts)
|
||||
pure $
|
||||
AB.mkAnyBackend $
|
||||
DBStepInfo @'MySQL sourceName sourceConfig Nothing explainResult ()
|
||||
|
@ -16,6 +16,7 @@ import Hasura.GraphQL.Transport.HTTP.Protocol
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.SQL.AnyBackend (AnyBackend)
|
||||
import Hasura.SQL.Backend
|
||||
import Hasura.Server.Types (RequestId)
|
||||
import Hasura.Session
|
||||
@ -41,7 +42,7 @@ runQuery ::
|
||||
UserInfo ->
|
||||
L.Logger L.Hasura ->
|
||||
SourceConfig 'MySQL ->
|
||||
OnBaseMonad IdentityT EncJSON ->
|
||||
OnBaseMonad IdentityT (Maybe (AnyBackend ExecutionStats), EncJSON) ->
|
||||
Maybe (PreparedQuery 'MySQL) ->
|
||||
ResolvedConnectionTemplate 'MySQL ->
|
||||
-- | Also return the time spent in the PG query; for telemetry.
|
||||
@ -50,7 +51,7 @@ runQuery reqId query fieldName _userInfo logger _sourceConfig tx genSql _ = do
|
||||
logQueryLog logger $ mkQueryLog query fieldName genSql reqId
|
||||
withElapsedTime $
|
||||
newSpan ("MySQL Query for root field " <>> fieldName) $
|
||||
run tx
|
||||
fmap snd (run tx)
|
||||
|
||||
runQueryExplain ::
|
||||
( MonadIO m,
|
||||
@ -60,7 +61,7 @@ runQueryExplain ::
|
||||
) =>
|
||||
DBStepInfo 'MySQL ->
|
||||
m EncJSON
|
||||
runQueryExplain (DBStepInfo _ _ _ action _) = run action
|
||||
runQueryExplain (DBStepInfo _ _ _ action _) = fmap arResult (run action)
|
||||
|
||||
run :: (MonadIO m, MonadBaseControl IO m, MonadError QErr m, MonadTrace m) => OnBaseMonad IdentityT a -> m a
|
||||
run = runIdentityT . runOnBaseMonad
|
||||
@ -73,7 +74,7 @@ mkQueryLog ::
|
||||
QueryLog
|
||||
mkQueryLog gqlQuery fieldName preparedSql requestId =
|
||||
-- @QueryLogKindDatabase Nothing@ means that the backend doesn't support connection templates
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase Nothing)
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase Nothing) Nothing
|
||||
where
|
||||
generatedQuery =
|
||||
preparedSql <&> \queryString ->
|
||||
|
@ -50,6 +50,7 @@ import Hasura.GraphQL.Execute.Backend
|
||||
ExplainPlan (..),
|
||||
OnBaseMonad (..),
|
||||
convertRemoteSourceRelationship,
|
||||
withNoStatistics,
|
||||
)
|
||||
import Hasura.GraphQL.Execute.Subscription.Plan
|
||||
( CohortId,
|
||||
@ -149,7 +150,8 @@ pgDBQueryPlan userInfo _env sourceName sourceConfig qrf reqHeaders operationName
|
||||
QueryOperationType G.OperationTypeQuery
|
||||
let preparedSQLWithQueryTags = appendPreparedSQLWithQueryTags (irToRootFieldPlan planVals preparedQuery) queryTagsComment
|
||||
let (action, preparedSQL) = mkCurPlanTx userInfo preparedSQLWithQueryTags
|
||||
pure $ DBStepInfo @('Postgres pgKind) sourceName sourceConfig preparedSQL action resolvedConnectionTemplate
|
||||
|
||||
pure $ DBStepInfo @('Postgres pgKind) sourceName sourceConfig preparedSQL (fmap withNoStatistics action) resolvedConnectionTemplate
|
||||
|
||||
pgDBQueryExplain ::
|
||||
forall pgKind m.
|
||||
@ -174,7 +176,7 @@ pgDBQueryExplain fieldName userInfo sourceName sourceConfig rootSelection reqHea
|
||||
withExplain = "EXPLAIN " <> textSQL
|
||||
let action = OnBaseMonad do
|
||||
PG.withQE dmlTxErrorHandler (PG.fromText withExplain) () True <&> \planList ->
|
||||
encJFromJValue $ ExplainPlan fieldName (Just textSQL) (Just $ map runIdentity planList)
|
||||
withNoStatistics $ encJFromJValue $ ExplainPlan fieldName (Just textSQL) (Just $ map runIdentity planList)
|
||||
resolvedConnectionTemplate <-
|
||||
applyConnectionTemplateResolverNonAdmin (_pscConnectionTemplateResolver sourceConfig) userInfo reqHeaders $
|
||||
Just $
|
||||
@ -326,7 +328,14 @@ pgDBMutationPlan userInfo _environment stringifyNum sourceName sourceConfig mrf
|
||||
MDBDelete s -> convertDelete userInfo s stringifyNum
|
||||
MDBFunction returnsSet s -> convertFunction userInfo returnsSet s
|
||||
where
|
||||
go resolvedConnectionTemplate v = DBStepInfo @('Postgres pgKind) sourceName sourceConfig Nothing v resolvedConnectionTemplate
|
||||
go resolvedConnectionTemplate v =
|
||||
DBStepInfo
|
||||
{ dbsiSourceName = sourceName,
|
||||
dbsiSourceConfig = sourceConfig,
|
||||
dbsiPreparedQuery = Nothing,
|
||||
dbsiAction = fmap withNoStatistics v,
|
||||
dbsiResolvedConnectionTemplate = resolvedConnectionTemplate
|
||||
}
|
||||
|
||||
-- subscription
|
||||
|
||||
|
@ -70,7 +70,7 @@ runPGQuery ::
|
||||
UserInfo ->
|
||||
L.Logger L.Hasura ->
|
||||
SourceConfig ('Postgres pgKind) ->
|
||||
OnBaseMonad (PG.TxET QErr) EncJSON ->
|
||||
OnBaseMonad (PG.TxET QErr) (Maybe (AB.AnyBackend ExecutionStats), EncJSON) ->
|
||||
Maybe EQ.PreparedSql ->
|
||||
ResolvedConnectionTemplate ('Postgres pgKind) ->
|
||||
-- | Also return the time spent in the PG query; for telemetry.
|
||||
@ -81,7 +81,7 @@ runPGQuery reqId query fieldName _userInfo logger sourceConfig tx genSql resolve
|
||||
withElapsedTime $
|
||||
newSpan ("Postgres Query for root field " <>> fieldName) $
|
||||
runQueryTx (_pscExecCtx sourceConfig) (GraphQLQuery resolvedConnectionTemplate) $
|
||||
runOnBaseMonad tx
|
||||
fmap snd (runOnBaseMonad tx)
|
||||
|
||||
runPGMutation ::
|
||||
( MonadIO m,
|
||||
@ -145,7 +145,7 @@ runPGQueryExplain ::
|
||||
m EncJSON
|
||||
runPGQueryExplain (DBStepInfo _ sourceConfig _ action resolvedConnectionTemplate) =
|
||||
runQueryTx (_pscExecCtx sourceConfig) (GraphQLQuery resolvedConnectionTemplate) $
|
||||
runOnBaseMonad action
|
||||
fmap arResult (runOnBaseMonad action)
|
||||
|
||||
mkQueryLog ::
|
||||
GQLReqUnparsed ->
|
||||
@ -155,7 +155,7 @@ mkQueryLog ::
|
||||
Maybe (ResolvedConnectionTemplate ('Postgres pgKind)) ->
|
||||
QueryLog
|
||||
mkQueryLog gqlQuery fieldName preparedSql requestId resolvedConnectionTemplate =
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase (mkBackendResolvedConnectionTemplate <$> resolvedConnectionTemplate))
|
||||
QueryLog gqlQuery ((fieldName,) <$> generatedQuery) requestId (QueryLogKindDatabase (mkBackendResolvedConnectionTemplate <$> resolvedConnectionTemplate)) Nothing
|
||||
where
|
||||
mkBackendResolvedConnectionTemplate ::
|
||||
ResolvedConnectionTemplate ('Postgres pgKind) ->
|
||||
@ -190,5 +190,6 @@ runPGMutationTransaction reqId query userInfo logger sourceConfig resolvedConnec
|
||||
runTxWithCtxAndUserInfo userInfo (_pscExecCtx sourceConfig) (Tx PG.ReadWrite Nothing) (GraphQLQuery resolvedConnectionTemplate) $
|
||||
flip OMap.traverseWithKey mutations \fieldName dbsi ->
|
||||
newSpan ("Postgres Mutation for root field " <>> fieldName) $
|
||||
runOnBaseMonad $
|
||||
dbsiAction dbsi
|
||||
fmap arResult $
|
||||
runOnBaseMonad $
|
||||
dbsiAction dbsi
|
||||
|
@ -1,6 +1,8 @@
|
||||
module Hasura.GraphQL.Execute.Backend
|
||||
( BackendExecute (..),
|
||||
DBStepInfo (..),
|
||||
ActionResult (..),
|
||||
withNoStatistics,
|
||||
ExecutionPlan,
|
||||
ExecutionStep (..),
|
||||
ExplainPlan (..),
|
||||
@ -238,10 +240,19 @@ data DBStepInfo b = DBStepInfo
|
||||
{ dbsiSourceName :: SourceName,
|
||||
dbsiSourceConfig :: SourceConfig b,
|
||||
dbsiPreparedQuery :: Maybe (PreparedQuery b),
|
||||
dbsiAction :: OnBaseMonad (ExecutionMonad b) EncJSON,
|
||||
dbsiAction :: OnBaseMonad (ExecutionMonad b) (ActionResult b),
|
||||
dbsiResolvedConnectionTemplate :: ResolvedConnectionTemplate b
|
||||
}
|
||||
|
||||
data ActionResult b = ActionResult
|
||||
{ arStatistics :: Maybe (ExecutionStatistics b),
|
||||
arResult :: EncJSON
|
||||
}
|
||||
|
||||
-- | Lift a result from the database into an 'ActionResult'.
|
||||
withNoStatistics :: EncJSON -> ActionResult b
|
||||
withNoStatistics arResult = ActionResult {arStatistics = Nothing, arResult}
|
||||
|
||||
-- | Provides an abstraction over the base monad in which a computation runs.
|
||||
--
|
||||
-- Given a transformer @t@ and a type @a@, @OnBaseMonad t a@ represents a
|
||||
@ -265,9 +276,12 @@ data DBStepInfo b = DBStepInfo
|
||||
-- be able to create new spans as part of the execution, and several use
|
||||
-- @MonadBaseControl IO@ to use 'try' in their error handling.
|
||||
newtype OnBaseMonad t a = OnBaseMonad
|
||||
{ runOnBaseMonad :: forall m. (MonadIO m, MonadBaseControl IO m, MonadTrace m, MonadError QErr m) => t m a
|
||||
{ runOnBaseMonad :: forall m. (Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m, MonadError QErr m) => t m a
|
||||
}
|
||||
|
||||
instance Functor (OnBaseMonad t) where
|
||||
fmap f (OnBaseMonad xs) = OnBaseMonad (fmap f xs)
|
||||
|
||||
-- | The result of an explain query: for a given root field (denoted by its name): the generated SQL
|
||||
-- query, and the detailed explanation obtained from the database (if any). We mostly use this type
|
||||
-- as an intermediary step, and immediately tranform any value we obtain into an equivalent JSON
|
||||
|
@ -23,7 +23,7 @@ import Hasura.GraphQL.Execute.Instances ()
|
||||
import Hasura.GraphQL.Execute.RemoteJoin.RemoteSchema qualified as RS
|
||||
import Hasura.GraphQL.Execute.RemoteJoin.Source qualified as S
|
||||
import Hasura.GraphQL.Execute.RemoteJoin.Types
|
||||
import Hasura.GraphQL.Logging (MonadQueryLog)
|
||||
import Hasura.GraphQL.Logging (MonadQueryLog, statsToAnyBackend)
|
||||
import Hasura.GraphQL.RemoteServer (execRemoteGQ)
|
||||
import Hasura.GraphQL.Transport.Backend qualified as TB
|
||||
import Hasura.GraphQL.Transport.HTTP.Protocol (GQLReqOutgoing, GQLReqUnparsed, _grOperationName, _unOperationName)
|
||||
@ -103,7 +103,7 @@ processRemoteJoins requestId logger env requestHeaders userInfo lhs maybeJoinTre
|
||||
userInfo
|
||||
logger
|
||||
_sjcSourceConfig
|
||||
(EB.dbsiAction _sjcStepInfo)
|
||||
(fmap (statsToAnyBackend @b) (EB.dbsiAction _sjcStepInfo))
|
||||
(EB.dbsiPreparedQuery _sjcStepInfo)
|
||||
(EB.dbsiResolvedConnectionTemplate _sjcStepInfo)
|
||||
pure $ encJToLBS $ snd response
|
||||
|
@ -1,8 +1,12 @@
|
||||
{-# LANGUAGE StandaloneKindSignatures #-}
|
||||
|
||||
-- |
|
||||
-- This module holds functions and data types used for logging at the GraphQL
|
||||
-- layer. In contrast with, logging at the HTTP server layer.
|
||||
module Hasura.GraphQL.Logging
|
||||
( QueryLog (..),
|
||||
ExecutionStats (..),
|
||||
statsToAnyBackend,
|
||||
GeneratedQuery (..),
|
||||
MonadQueryLog (..),
|
||||
QueryLogKind (..),
|
||||
@ -11,12 +15,19 @@ where
|
||||
|
||||
import Data.Aeson qualified as J
|
||||
import Data.HashMap.Strict qualified as Map
|
||||
import Data.Kind (Type)
|
||||
import Data.Text.Extended
|
||||
import Hasura.EncJSON (EncJSON)
|
||||
import Hasura.GraphQL.Execute.Backend (ActionResult (..))
|
||||
import Hasura.GraphQL.Namespace (RootFieldAlias)
|
||||
import Hasura.GraphQL.Transport.HTTP.Protocol (GQLReqUnparsed)
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.DDL.ConnectionTemplate (BackendResolvedConnectionTemplate (..))
|
||||
import Hasura.RQL.Types.Backend (Backend (ExecutionStatistics))
|
||||
import Hasura.SQL.AnyBackend (AnyBackend, dispatchAnyBackend', mkAnyBackend)
|
||||
import Hasura.SQL.Backend (BackendType)
|
||||
import Hasura.SQL.Tag (HasTag)
|
||||
import Hasura.Server.Types (RequestId)
|
||||
import Hasura.Tracing (TraceT)
|
||||
|
||||
@ -26,11 +37,28 @@ data QueryLog = QueryLog
|
||||
{ _qlQuery :: !GQLReqUnparsed,
|
||||
_qlGeneratedSql :: !(Maybe (RootFieldAlias, GeneratedQuery)),
|
||||
_qlRequestId :: !RequestId,
|
||||
_qlKind :: !QueryLogKind
|
||||
_qlKind :: !QueryLogKind,
|
||||
_qlStatistics :: !(Maybe (AnyBackend ExecutionStats))
|
||||
}
|
||||
|
||||
-- | 'ExecutionStatistics' is a type family, which means we can't partially
|
||||
-- apply it (in 'AnyBackend', for example). To get round this, we have a
|
||||
-- newtype that really just wraps the type family.
|
||||
type ExecutionStats :: BackendType -> Type
|
||||
newtype ExecutionStats b = ExecutionStats (ExecutionStatistics b)
|
||||
|
||||
-- | When we want to log anything from 'DBStepInfo', we first need to transform
|
||||
-- the backend-specific execution statistics into 'AnyBackend' statistics. This
|
||||
-- is fine in practice because all we do with it is log it as JSON.
|
||||
statsToAnyBackend :: forall b. (HasTag b) => ActionResult b -> (Maybe (AnyBackend ExecutionStats), EncJSON)
|
||||
statsToAnyBackend ActionResult {..} =
|
||||
(fmap (mkAnyBackend @b . ExecutionStats) arStatistics, arResult)
|
||||
|
||||
deriving newtype instance Backend b => J.ToJSON (ExecutionStats b)
|
||||
|
||||
data QueryLogKind
|
||||
= QueryLogKindDatabase (Maybe (BackendResolvedConnectionTemplate))
|
||||
| QueryLogKindDatabaseResponse (Maybe (BackendResolvedConnectionTemplate))
|
||||
| QueryLogKindAction
|
||||
| QueryLogKindRemoteSchema
|
||||
| QueryLogKindCached
|
||||
@ -39,6 +67,7 @@ data QueryLogKind
|
||||
instance J.ToJSON QueryLogKind where
|
||||
toJSON = \case
|
||||
QueryLogKindDatabase _ -> "database"
|
||||
QueryLogKindDatabaseResponse _ -> "database-response"
|
||||
QueryLogKindAction -> "action"
|
||||
QueryLogKindRemoteSchema -> "remote-schema"
|
||||
QueryLogKindCached -> "cached"
|
||||
@ -50,13 +79,16 @@ data GeneratedQuery = GeneratedQuery
|
||||
}
|
||||
|
||||
instance J.ToJSON QueryLog where
|
||||
toJSON (QueryLog gqlQuery generatedQuery reqId kind) =
|
||||
toJSON (QueryLog gqlQuery generatedQuery reqId kind mstatistics) =
|
||||
J.object $
|
||||
[ "query" J..= gqlQuery,
|
||||
-- NOTE: this customizes the default JSON instance of a pair
|
||||
"generated_sql" J..= fmap fromPair generatedQuery,
|
||||
"request_id" J..= reqId,
|
||||
"kind" J..= kind
|
||||
"kind" J..= kind,
|
||||
"statistics" J..= case mstatistics of
|
||||
Just statistics -> dispatchAnyBackend' @J.ToJSON statistics J.toJSON
|
||||
Nothing -> J.toJSON ()
|
||||
]
|
||||
<> maybe [] (\val -> ["connection_template" J..= val]) (getResolvedConnectionTemplate kind)
|
||||
where
|
||||
|
@ -9,12 +9,13 @@ import Hasura.Base.Error
|
||||
import Hasura.EncJSON
|
||||
import Hasura.GraphQL.Execute.Backend
|
||||
import Hasura.GraphQL.Execute.Subscription.Plan
|
||||
import Hasura.GraphQL.Logging (MonadQueryLog)
|
||||
import Hasura.GraphQL.Logging (ExecutionStats, MonadQueryLog)
|
||||
import Hasura.GraphQL.Namespace (RootFieldAlias)
|
||||
import Hasura.GraphQL.Transport.HTTP.Protocol
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.SQL.AnyBackend (AnyBackend)
|
||||
import Hasura.SQL.Backend
|
||||
import Hasura.Server.Types (RequestId)
|
||||
import Hasura.Session
|
||||
@ -37,7 +38,7 @@ class BackendExecute b => BackendTransport (b :: BackendType) where
|
||||
UserInfo ->
|
||||
L.Logger L.Hasura ->
|
||||
SourceConfig b ->
|
||||
OnBaseMonad (ExecutionMonad b) EncJSON ->
|
||||
OnBaseMonad (ExecutionMonad b) (Maybe (AnyBackend ExecutionStats), EncJSON) ->
|
||||
Maybe (PreparedQuery b) ->
|
||||
ResolvedConnectionTemplate b ->
|
||||
m (DiffTime, EncJSON)
|
||||
|
@ -50,6 +50,7 @@ import Hasura.GraphQL.Logging
|
||||
( MonadQueryLog (logQueryLog),
|
||||
QueryLog (..),
|
||||
QueryLogKind (..),
|
||||
statsToAnyBackend,
|
||||
)
|
||||
import Hasura.GraphQL.Namespace
|
||||
import Hasura.GraphQL.ParameterizedQueryHash
|
||||
@ -395,7 +396,7 @@ runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
|
||||
case fmap decodeGQResp cachedValue of
|
||||
-- If we get a cache hit, annotate the response with metadata and return it.
|
||||
Just cachedResponseData -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindCached
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindCached Nothing
|
||||
pure $
|
||||
AnnotatedResponse
|
||||
{ arQueryType = Telem.Query,
|
||||
@ -469,15 +470,15 @@ runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
|
||||
AB.dispatchAnyBackend @BackendTransport
|
||||
exists
|
||||
\(EB.DBStepInfo _ sourceConfig genSql tx resolvedConnectionTemplate :: EB.DBStepInfo b) ->
|
||||
runDBQuery @b reqId reqUnparsed fieldName userInfo logger sourceConfig tx genSql resolvedConnectionTemplate
|
||||
runDBQuery @b reqId reqUnparsed fieldName userInfo logger sourceConfig (fmap (statsToAnyBackend @b) tx) genSql resolvedConnectionTemplate
|
||||
finalResponse <-
|
||||
RJ.processRemoteJoins reqId logger env reqHeaders userInfo resp remoteJoins reqUnparsed
|
||||
pure $ AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse []
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema Nothing
|
||||
runRemoteGQ fieldName rsi resultCustomizer gqlReq remoteJoins
|
||||
E.ExecStepAction aep _ remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindAction
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindAction Nothing
|
||||
(time, resp) <- doQErr $ do
|
||||
(time, (resp, _)) <- EA.runActionExecution userInfo aep
|
||||
finalResponse <-
|
||||
@ -485,7 +486,7 @@ runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
|
||||
pure (time, finalResponse)
|
||||
pure $ AnnotatedResponsePart time Telem.Empty resp []
|
||||
E.ExecStepRaw json -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindIntrospection
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindIntrospection Nothing
|
||||
buildRaw json
|
||||
-- For `ExecStepMulti`, execute all steps and then concat them in a list
|
||||
E.ExecStepMulti lst -> do
|
||||
@ -502,15 +503,15 @@ runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
|
||||
AB.dispatchAnyBackend @BackendTransport
|
||||
exists
|
||||
\(EB.DBStepInfo _ sourceConfig genSql tx resolvedConnectionTemplate :: EB.DBStepInfo b) ->
|
||||
runDBMutation @b reqId reqUnparsed fieldName userInfo logger sourceConfig tx genSql resolvedConnectionTemplate
|
||||
runDBMutation @b reqId reqUnparsed fieldName userInfo logger sourceConfig (fmap EB.arResult tx) genSql resolvedConnectionTemplate
|
||||
finalResponse <-
|
||||
RJ.processRemoteJoins reqId logger env reqHeaders userInfo resp remoteJoins reqUnparsed
|
||||
pure $ AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse responseHeaders
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindRemoteSchema Nothing
|
||||
runRemoteGQ fieldName rsi resultCustomizer gqlReq remoteJoins
|
||||
E.ExecStepAction aep _ remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindAction
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindAction Nothing
|
||||
(time, (resp, hdrs)) <- doQErr $ do
|
||||
(time, (resp, hdrs)) <- EA.runActionExecution userInfo aep
|
||||
finalResponse <-
|
||||
@ -518,7 +519,7 @@ runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
|
||||
pure (time, (finalResponse, hdrs))
|
||||
pure $ AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs
|
||||
E.ExecStepRaw json -> do
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindIntrospection
|
||||
logQueryLog logger $ QueryLog reqUnparsed Nothing reqId QueryLogKindIntrospection Nothing
|
||||
buildRaw json
|
||||
-- For `ExecStepMulti`, execute all steps and then concat them in a list
|
||||
E.ExecStepMulti lst -> do
|
||||
|
@ -505,7 +505,7 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
Left _err -> throwError ()
|
||||
case cachedValue of
|
||||
Just cachedResponseData -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindCached
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindCached Nothing
|
||||
let reportedExecutionTime = 0
|
||||
liftIO $ recordGQLQuerySuccess reportedExecutionTime gqlOpType
|
||||
sendSuccResp cachedResponseData opName parameterizedQueryHash $ ES.SubscriptionMetadata reportedExecutionTime
|
||||
@ -526,17 +526,17 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
userInfo
|
||||
logger
|
||||
sourceConfig
|
||||
tx
|
||||
(fmap (statsToAnyBackend @b) tx)
|
||||
genSql
|
||||
resolvedConnectionTemplate
|
||||
finalResponse <-
|
||||
RJ.processRemoteJoins requestId logger env reqHdrs userInfo resp remoteJoins q
|
||||
pure $ AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse []
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema Nothing
|
||||
runRemoteGQ requestId q fieldName userInfo reqHdrs rsi resultCustomizer gqlReq remoteJoins
|
||||
E.ExecStepAction actionExecPlan _ remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction Nothing
|
||||
(time, (resp, _)) <- doQErr $ do
|
||||
(time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan
|
||||
finalResponse <-
|
||||
@ -544,7 +544,7 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
pure (time, (finalResponse, hdrs))
|
||||
pure $ AnnotatedResponsePart time Telem.Empty resp []
|
||||
E.ExecStepRaw json -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindIntrospection
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindIntrospection Nothing
|
||||
buildRaw json
|
||||
E.ExecStepMulti lst -> do
|
||||
allResponses <- traverse getResponse lst
|
||||
@ -603,14 +603,14 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
userInfo
|
||||
logger
|
||||
sourceConfig
|
||||
tx
|
||||
(fmap EB.arResult tx)
|
||||
genSql
|
||||
resolvedConnectionTemplate
|
||||
finalResponse <-
|
||||
RJ.processRemoteJoins requestId logger env reqHdrs userInfo resp remoteJoins q
|
||||
pure $ AnnotatedResponsePart telemTimeIO_DT Telem.Local finalResponse []
|
||||
E.ExecStepAction actionExecPlan _ remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction Nothing
|
||||
(time, (resp, hdrs)) <- doQErr $ do
|
||||
(time, (resp, hdrs)) <- EA.runActionExecution userInfo actionExecPlan
|
||||
finalResponse <-
|
||||
@ -618,10 +618,10 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
pure (time, (finalResponse, hdrs))
|
||||
pure $ AnnotatedResponsePart time Telem.Empty resp $ fromMaybe [] hdrs
|
||||
E.ExecStepRemote rsi resultCustomizer gqlReq remoteJoins -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindRemoteSchema Nothing
|
||||
runRemoteGQ requestId q fieldName userInfo reqHdrs rsi resultCustomizer gqlReq remoteJoins
|
||||
E.ExecStepRaw json -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindIntrospection
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindIntrospection Nothing
|
||||
buildRaw json
|
||||
E.ExecStepMulti lst -> do
|
||||
allResponses <- traverse getResponse lst
|
||||
@ -632,7 +632,7 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
E.SubscriptionExecutionPlan subExec -> do
|
||||
case subExec of
|
||||
E.SEAsyncActionsWithNoRelationships actions -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction Nothing
|
||||
liftIO do
|
||||
let allActionIds = map fst $ toList actions
|
||||
case NE.nonEmpty allActionIds of
|
||||
@ -676,11 +676,11 @@ onStart env enabledLogTypes serverEnv wsConn shouldCaptureVariables (StartMsg op
|
||||
-- Update async action query subscription state
|
||||
case NE.nonEmpty (toList actionIds) of
|
||||
Nothing -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId (QueryLogKindDatabase Nothing)
|
||||
logQueryLog logger $ QueryLog q Nothing requestId (QueryLogKindDatabase Nothing) Nothing
|
||||
-- No async action query fields present, do nothing.
|
||||
pure ()
|
||||
Just nonEmptyActionIds -> do
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction
|
||||
logQueryLog logger $ QueryLog q Nothing requestId QueryLogKindAction Nothing
|
||||
liftIO $ do
|
||||
let asyncActionQueryLive =
|
||||
ES.LAAQOnSourceDB $
|
||||
|
@ -116,6 +116,7 @@ class
|
||||
ToJSON (BackendConfig b),
|
||||
ToJSON (Column b),
|
||||
ToJSON (ConstraintName b),
|
||||
ToJSON (ExecutionStatistics b),
|
||||
ToJSON (FunctionArgument b),
|
||||
ToJSON (FunctionName b),
|
||||
ToJSON (ScalarType b),
|
||||
@ -311,6 +312,12 @@ class
|
||||
resolveConnectionTemplate :: SourceConfig b -> ConnectionTemplateRequestContext b -> Either QErr EncJSON
|
||||
resolveConnectionTemplate _ _ = Left (err400 (NotSupported) "connection template is not implemented")
|
||||
|
||||
-- | Information about the query execution that may be useful for debugging
|
||||
-- or reporting.
|
||||
type ExecutionStatistics b :: Type
|
||||
|
||||
type ExecutionStatistics b = ()
|
||||
|
||||
-- functions on types
|
||||
isComparableType :: ScalarType b -> Bool
|
||||
isNumType :: ScalarType b -> Bool
|
||||
|
Loading…
Reference in New Issue
Block a user