packages feed

google-cloud-logging 0.1.0.0 → 1.1.0.0

raw patch · 6 files changed

+279/−40 lines, 6 filesdep +bytestringdep +tastydep +tasty-hunitdep ~google-cloud-commonsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring, tasty, tasty-hunit

Dependency ranges changed: google-cloud-common

API changes (from Hackage documentation)

- Google.Cloud.Logging.Logs: [$sel:logNames:ListLogsResp] :: ListLogsResp -> [String]
- Google.Cloud.Logging.Logs: [$sel:nextPageToken:ListLogsResp] :: ListLogsResp -> Maybe String
- Google.Cloud.Logging.Logs: instance GHC.Generics.Generic Google.Cloud.Logging.Logs.ListLogsResp
- Google.Cloud.Logging.Logs: instance GHC.Show.Show Google.Cloud.Logging.Logs.ListLogsOps
- Google.Cloud.Logging.Logs: instance GHC.Show.Show Google.Cloud.Logging.Logs.ListLogsResp
- Google.Cloud.Logging.Logs: instance GHC.Show.Show Google.Cloud.Logging.Logs.Resource
+ Google.Cloud.Logging.Logs: ListLogsOps :: Maybe [String] -> Maybe Integer -> Maybe String -> ListLogsOps
+ Google.Cloud.Logging.Logs: [logNames] :: ListLogsResp -> [String]
+ Google.Cloud.Logging.Logs: [nextPageToken] :: ListLogsResp -> Maybe String
+ Google.Cloud.Logging.Logs: [pageSize] :: ListLogsOps -> Maybe Integer
+ Google.Cloud.Logging.Logs: [pageToken] :: ListLogsOps -> Maybe String
+ Google.Cloud.Logging.Logs: [resourceNames] :: ListLogsOps -> Maybe [String]
+ Google.Cloud.Logging.Logs: data ListLogsOps
+ Google.Cloud.Logging.Logs: defaultListLogsOps :: ListLogsOps
+ Google.Cloud.Logging.Logs: getSettings :: Resource -> IO (Either String Settings)
+ Google.Cloud.Logging.Logs: googleLoggingUrl :: String
+ Google.Cloud.Logging.Logs: instance Data.Aeson.Types.FromJSON.FromJSON Google.Cloud.Logging.Logs.DefaultSinkConfig
+ Google.Cloud.Logging.Logs: instance Data.Aeson.Types.FromJSON.FromJSON Google.Cloud.Logging.Logs.Settings
+ Google.Cloud.Logging.Logs: instance GHC.Classes.Eq Google.Cloud.Logging.Logs.DefaultSinkConfig
+ Google.Cloud.Logging.Logs: instance GHC.Classes.Eq Google.Cloud.Logging.Logs.Settings
+ Google.Cloud.Logging.Logs: instance GHC.Internal.Show.Show Google.Cloud.Logging.Logs.DefaultSinkConfig
+ Google.Cloud.Logging.Logs: instance GHC.Internal.Show.Show Google.Cloud.Logging.Logs.ListLogsOps
+ Google.Cloud.Logging.Logs: instance GHC.Internal.Show.Show Google.Cloud.Logging.Logs.ListLogsResp
+ Google.Cloud.Logging.Logs: instance GHC.Internal.Show.Show Google.Cloud.Logging.Logs.Resource
+ Google.Cloud.Logging.Logs: instance GHC.Internal.Show.Show Google.Cloud.Logging.Logs.Settings
- Google.Cloud.Logging.Logs: listLogs :: Resource -> Maybe ListLogsOps -> IO (Either String ListLogsResp)
+ Google.Cloud.Logging.Logs: listLogs :: Resource -> ListLogsOps -> IO (Either String ListLogsResp)

Files

CHANGELOG.md view
@@ -8,4 +8,8 @@  ## Unreleased +## 1.1.0.0 - 2025-09-11++- Synchronized version bump for v1.1.0.0 release.+ ## 0.1.0.0 - YYYY-MM-DD
README.md view
@@ -3,3 +3,52 @@ Haskell idiomatic client for [Google Cloud Platform](https://cloud.google.com/) Logging service.  Full docs are available at https://github.com/tusharad/google-cloud-haskell++## Installation++- Cabal: add to your `.cabal`+  - `build-depends: google-cloud-logging == 1.1.0.0`+- Stack: add to your `package.yaml`+  - `dependencies: - google-cloud-logging == 1.1.0.0`++This package depends on `google-cloud-common` for auth and HTTP helpers.++## Authentication++Authentication is handled by `google-cloud-common` and follows this order:++1. Use `GOOGLE_APPLICATION_CREDENTIALS` to load a Service Account JSON and+   exchange a signed JWT for an access token.+2. Otherwise, use the Compute metadata server (suitable for GCE/GKE).++## Examples++Minimal examples using `Google.Cloud.Logging.Logs`:++```haskell+{-# LANGUAGE OverloadedStrings #-}++import Google.Cloud.Logging.Logs++-- List log names under a project+listLogsExample :: IO ()+listLogsExample = do+  let resource = Projects "my-gcp-project"+  eResp <- listLogs resource defaultListLogsOps+  case eResp of+    Left err -> putStrLn ("Error: " <> err)+    Right res -> print (logNames res)++-- Fetch logging settings for a project+getSettingsExample :: IO ()+getSettingsExample = do+  let resource = Projects "my-gcp-project"+  eRes <- getSettings resource+  case eRes of+    Left err -> putStrLn ("Settings error: " <> err)+    Right settings -> print settings+```++## License++MIT © Contributors
Setup.hs view
@@ -1,2 +1,3 @@ import Distribution.Simple+ main = defaultMain
google-cloud-logging.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.37.0.+-- This file has been generated from package.yaml by hpack version 0.38.1. -- -- see: https://github.com/sol/hpack  name:           google-cloud-logging-version:        0.1.0.0+version:        1.1.0.0 synopsis:       GCP Client for Haskell description:    GCP Logging client for Haskell category:       Web@@ -36,7 +36,8 @@   build-depends:       aeson <3     , base >=4.7 && <5-    , google-cloud-common+    , bytestring >=0.9.1.4+    , google-cloud-common >=1.1.0.0 && <1.2.0.0   default-language: Haskell2010  test-suite google-cloud-logging-test@@ -50,6 +51,9 @@   build-depends:       aeson <3     , base >=4.7 && <5-    , google-cloud-common+    , bytestring >=0.9.1.4+    , google-cloud-common >=1.1.0.0 && <1.2.0.0     , google-cloud-logging+    , tasty >=1.4+    , tasty-hunit >=0.10   default-language: Haskell2010
src/Google/Cloud/Logging/Logs.hs view
@@ -1,46 +1,82 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} --- | A client module for interacting with Google Cloud Logging's log management API.------ This module implements the v2 REST API for listing logs from GCP resources.--- For API details, see: <https://cloud.google.com/logging/docs/reference/v2/rest/v2/logs/list GCP Logging API Documentation>+{- |+Module      : Google.Cloud.Logging.Logs+License     : MIT+Maintainer  : maintainers@google-cloud-haskell+Stability   : experimental +A client module for interacting with Google Cloud Logging's log management API.+This module implements parts of the v2 REST API for listing logs and fetching+settings.++For API details, see:+<https://cloud.google.com/logging/docs/reference/v2/rest/v2/logs/list GCP Logging API Documentation>+-} module Google.Cloud.Logging.Logs   ( listLogs   , Resource (..)   , ListLogsResp (..)+  , googleLoggingUrl+  , defaultListLogsOps+  , ListLogsOps (..)+  , getSettings   ) where  import Data.Aeson-import GHC.Generics+import qualified Data.ByteString.Char8 as BS+import Data.Maybe import Google.Cloud.Common.Core --- | Represents GCP resources that can contain logs.--- Constructors take the resource identifier as a String.+{- | Logging url for GCP Logging service+url = "https://logging.googleapis.com/v2"+-}+googleLoggingUrl :: String+googleLoggingUrl = "https://logging.googleapis.com/v2"++{- | Represents GCP resources that can contain logs.+Constructors take the resource identifier as a String.+-} data Resource-  = Projects String       -- ^ A GCP Project resource with the given project ID-  | Organizations String  -- ^ A GCP Organization resource with the given organization ID-  | BillingAccount String -- ^ A GCP Billing Account resource with the given billing account ID-  | Folders String        -- ^ A GCP Folder resource with the given folder ID+  = -- | A GCP Project resource with the given project ID+    Projects String+  | -- | A GCP Organization resource with the given organization ID+    Organizations String+  | -- | A GCP Billing Account resource with the given billing account ID+    BillingAccount String+  | -- | A GCP Folder resource with the given folder ID+    Folders String   deriving (Eq, Show)  -- | Options for customizing the 'listLogs' request data ListLogsOps = ListLogsOps-  { resourceNames :: [String]     -- ^ List of parent resource names to search (corresponds to 'resourceNames' query parameter)-  , pageSize :: Maybe Integer     -- ^ Maximum number of results to return (server may return fewer)-  , pageToken :: Maybe String     -- ^ Pagination token from previous 'ListLogsResp'+  { resourceNames :: Maybe [String]+  -- ^ List of parent resource names to search (corresponds to 'resourceNames' query parameter)+  , pageSize :: Maybe Integer+  -- ^ Maximum number of results to return (server may return fewer)+  , pageToken :: Maybe String+  -- ^ Pagination token from previous 'ListLogsResp'   }   deriving (Eq, Show)  -- | Response from the Cloud Logging API containing log resources data ListLogsResp = ListLogsResp-  { logNames :: [String]         -- ^ List of log resource names matching the request-  , nextPageToken :: Maybe String -- ^ Pagination token for next batch of results (if any)+  { logNames :: [String]+  -- ^ List of log resource names matching the request+  , nextPageToken :: Maybe String+  -- ^ Pagination token for next batch of results (if any)   }-  deriving (Eq, Show, Generic, FromJSON)+  deriving (Eq, Show) +instance FromJSON ListLogsResp where+  parseJSON = withObject "ListLogsResp" $ \v ->+    ListLogsResp+      <$> v .: "logNames"+      <*> v .:? "nextPageToken"+ -- | Internal helper to convert a Resource to a URL path component toResource :: Resource -> [String] toResource resource =@@ -50,28 +86,131 @@     BillingAccount str -> ["billingAccounts", str]     Folders str -> ["folders", str] --- | List log resource names from a GCP resource------ Example:------ > listLogs (Projects "my-project") Nothing------ This makes a request to @v2/projects/my-project/logs@------ Returns 'Either' with error message or 'ListLogsResp' containing:--- * Matching log resource names--- * Pagination token for subsequent requests-listLogs :: Resource           -- ^ Parent GCP resource to list logs from-         -> Maybe ListLogsOps  -- ^ Optional parameters for pagination and filtering-         -> IO (Either String ListLogsResp)-listLogs resource _ =+{- | List log resource names from a GCP resource++Example:++> listLogs (Projects "my-project") Nothing++This makes a request to @v2/projects/my-project/logs@++Returns 'Either' with error message or 'ListLogsResp' containing:+* Matching log resource names+* Pagination token for subsequent requests+-}+listLogs ::+  -- | Parent GCP resource to list logs from+  Resource ->+  -- | parameters for pagination and filtering and other resource names+  ListLogsOps ->+  IO (Either String ListLogsResp)+listLogs resource ListLogsOps {..} = do+  let qParams =+        concat+          [ maybeToList $ fmap (("pageSize",) . Just . BS.pack . show) pageSize+          , maybeToList $ fmap (("pageToken",) . Just . BS.pack) pageToken+          , maybe [] (map (("resourceNames",) . Just . BS.pack)) resourceNames+          ]   doRequestJSON     RequestOptions       { reqMethod = GET       , reqUrl = googleLoggingUrl-      , mbQueryParams = Nothing+      , mbQueryParams = Just qParams       , mbReqBody = Nothing       , mbReqHeaders = Nothing       , mbReqPath =           Just $ toPath $ toResource resource <> ["logs"]+      }++{- | Helper function to pass ListLogsOps+| Example+> listLogs (Projects "my-project") (defaultListLogsOps { resourceNames = Just ["projects/my-project-id"] })+-}+defaultListLogsOps :: ListLogsOps+defaultListLogsOps =+  ListLogsOps+    { resourceNames = Nothing+    , pageSize = Nothing+    , pageToken = Nothing+    }++-- | https://cloud.google.com/logging/docs/reference/v2/rest/v2/Settings++-- | Represents the configuration of the default log sink in Google Cloud Logging settings.+data DefaultSinkConfig = DefaultSinkConfig+  { destination :: Maybe String+  -- ^ The export destination for the default sink (e.g., a Cloud Storage bucket).+  , filter :: Maybe String+  -- ^ The filter that determines which log entries are exported.+  , outputVersionFormat :: Maybe String+  -- ^ The format of the log entry output (e.g., 'V2').+  }+  deriving (Show, Eq)++instance FromJSON DefaultSinkConfig where+  parseJSON = withObject "DefaultSinkConfig" $ \v ->+    DefaultSinkConfig+      <$> v .:? "destination"+      <*> v .:? "filter"+      <*> v .:? "outputVersionFormat"++-- | Represents the settings resource in Google Cloud Logging.+data Settings = Settings+  { name :: String+  -- ^ The resource name of the settings.+  , kmsKeyName :: Maybe String+  -- ^ The name of the Cloud KMS key used for log encryption.+  , kmsServiceAccountId :: Maybe String+  -- ^ The service account ID used for accessing the KMS key.+  , storageLocation :: Maybe String+  -- ^ The storage location for log data.+  , disableDefaultSink :: Maybe Bool+  -- ^ Indicates whether the default sink is disabled.+  , defaultSinkConfig :: Maybe DefaultSinkConfig+  -- ^ Configuration details of the default sink.+  , loggingServiceAccountId :: Maybe String+  -- ^ The service account ID used by the logging service.+  }+  deriving (Show, Eq)++instance FromJSON Settings where+  parseJSON = withObject "Settings" $ \v ->+    Settings+      <$> v .: "name"+      <*> v .:? "kmsKeyName"+      <*> v .:? "kmsServiceAccountId"+      <*> v .:? "storageLocation"+      <*> v .:? "disableDefaultSink"+      <*> v .:? "defaultSinkConfig"+      <*> v .:? "loggingServiceAccountId"++{- | Fetches the logging settings for a specified resource.++This function sends a GET request to the Google Cloud Logging API to retrieve the+settings associated with the provided resource.++@+eResult <- getSettings myResource+case eResult of+  Left err -> putStrLn $ "Error: " ++ err+  Right settings -> print settings+@++@since 0.1.0+-}+getSettings ::+  -- | The resource for which to retrieve logging settings.+  Resource ->+  -- | Either an error message or the retrieved settings.+  IO (Either String Settings)+getSettings resource =+  doRequestJSON+    RequestOptions+      { reqMethod = GET+      , reqUrl = googleLoggingUrl+      , mbQueryParams = Nothing+      , mbReqBody = Nothing+      , mbReqHeaders = Nothing+      , mbReqPath =+          Just $ toPath $ toResource resource <> ["settings"]       }
test/Spec.hs view
@@ -1,2 +1,44 @@+{-# LANGUAGE OverloadedStrings #-}++module Main (main) where++import Data.Aeson (eitherDecode)+import qualified Data.ByteString.Lazy.Char8 as BSL+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit (assertBool, assertEqual, testCase)++import Google.Cloud.Logging.Logs+  ( ListLogsOps (..)+  , ListLogsResp (..)+  , Resource (..)+  , defaultListLogsOps+  , googleLoggingUrl+  )+ main :: IO ()-main = putStrLn "Test suite not yet implemented"+main = defaultMain tests++tests :: TestTree+tests =+  testGroup+    "google-cloud-logging"+    [ testCase "googleLoggingUrl is v2 endpoint" $ do+        assertEqual "Endpoint" "https://logging.googleapis.com/v2" googleLoggingUrl+    , testCase "defaultListLogsOps has all fields Nothing" $ do+        let d = defaultListLogsOps+        assertEqual "resourceNames" Nothing (resourceNames d)+        assertEqual "pageSize" Nothing (pageSize d)+        assertEqual "pageToken" Nothing (pageToken d)+    , testCase "Decode ListLogsResp with nextPageToken" $ do+        let json =+              BSL.pack+                "{\n  \"logNames\": [\"projects/p/logs/a\", \"projects/p/logs/b\"],\n  \"nextPageToken\": \"tok\"\n}"+        case eitherDecode json of+          Left err -> assertBool ("Failed to decode: " <> err) False+          Right (ListLogsResp names tok) -> do+            assertEqual "names" ["projects/p/logs/a", "projects/p/logs/b"] names+            assertEqual "token" (Just "tok") tok+    , testCase "Resource Show/Eq constructors" $ do+        assertEqual "Projects" (Projects "p") (Projects "p")+        assertEqual "Show Organizations" "Organizations \"o\"" (show (Organizations "o"))+    ]