graphql-engine/server/src-lib/Hasura/RQL/DDL/OpenTelemetry.hs

104 lines
3.7 KiB
Haskell
Raw Normal View History

module Hasura.RQL.DDL.OpenTelemetry
( runSetOpenTelemetryConfig,
runSetOpenTelemetryStatus,
parseOtelExporterConfig,
parseOtelBatchSpanProcessorConfig,
)
where
import Control.Lens ((.~))
import Data.Bifunctor (first)
import Data.Environment (Environment)
import Data.Map.Strict qualified as Map
import Data.Text qualified as Text
import Hasura.Base.Error (Code (InvalidParams), QErr, err400)
import Hasura.EncJSON
import Hasura.Metadata.Class ()
import Hasura.Prelude hiding (first)
import Hasura.RQL.DDL.Headers (makeHeadersFromConf)
import Hasura.RQL.Types.Common (successMsg)
import Hasura.RQL.Types.Metadata
import Hasura.RQL.Types.Metadata.Object
import Hasura.RQL.Types.OpenTelemetry
import Hasura.RQL.Types.SchemaCache.Build
import Network.HTTP.Client (Request (requestHeaders), requestFromURI)
import Network.URI (parseURI)
-- | Set the OpenTelemetry configuration to the provided value.
runSetOpenTelemetryConfig ::
(MonadError QErr m, MetadataM m, CacheRWM m) =>
OpenTelemetryConfig ->
m EncJSON
runSetOpenTelemetryConfig otelConfig = do
withNewInconsistentObjsCheck $
buildSchemaCacheFor (MOOpenTelemetry OtelSubobjectAll) $
MetadataModifier $
metaOpenTelemetryConfig .~ otelConfig
pure successMsg
-- | Set just the "status" field of the OpenTelemetry configuration.
runSetOpenTelemetryStatus ::
(MonadError QErr m, MetadataM m, CacheRWM m) =>
OtelStatus ->
m EncJSON
runSetOpenTelemetryStatus otelStatus = do
withNewInconsistentObjsCheck $
buildSchemaCacheFor (MOOpenTelemetry OtelSubobjectAll) $
MetadataModifier $
metaOpenTelemetryConfig . ocStatus .~ otelStatus
pure successMsg
-- | Smart constructor for 'OtelExporterInfo'.
--
-- Returns a @Left qErr@ to signal a validation error. Returns @Right Nothing@
-- to signal that the exporter should be disabled without raising an error.
--
-- Allows the trace endpoint to be unset if the entire OpenTelemetry system is
-- disabled.
parseOtelExporterConfig ::
OtelStatus ->
Environment ->
OtelExporterConfig ->
Either QErr (Maybe OtelExporterInfo)
parseOtelExporterConfig otelStatus env OtelExporterConfig {..} = do
-- First validate everything but the trace endpoint
headers <- makeHeadersFromConf env _oecHeaders
-- Allow the trace endpoint to be unset when OpenTelemetry is disabled
case _oecTracesEndpoint of
Nothing ->
case otelStatus of
OtelDisabled ->
pure Nothing
OtelEnabled -> Left (err400 InvalidParams "Missing traces endpoint")
Just rawTracesEndpoint -> do
tracesUri <-
maybeToEither (err400 InvalidParams "Invalid URL") $
parseURI $
Text.unpack rawTracesEndpoint
uriRequest <-
first (err400 InvalidParams . tshow) $ requestFromURI tracesUri
pure $
Just $
OtelExporterInfo
{ _oteleiTracesBaseRequest =
uriRequest
{ requestHeaders = headers ++ requestHeaders uriRequest
},
_oteleiResourceAttributes =
Map.fromList $
map
(\NameValue {nv_name, nv_value} -> (nv_name, nv_value))
_oecResourceAttributes
}
-- Smart constructor. Consistent with defaults.
parseOtelBatchSpanProcessorConfig ::
OtelBatchSpanProcessorConfig -> Either QErr OtelBatchSpanProcessorInfo
parseOtelBatchSpanProcessorConfig OtelBatchSpanProcessorConfig {..} = do
_obspiMaxExportBatchSize <-
if _obspcMaxExportBatchSize > 0
then Right _obspcMaxExportBatchSize
else Left (err400 InvalidParams "max_export_batch_size must be a positive integer")
let _obspiMaxQueueSize = 4 * _obspiMaxExportBatchSize -- consistent with default value of 2048
pure OtelBatchSpanProcessorInfo {..}