diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,7 @@
+## 0.1.1.8 (2024-10-31)
+
+ * Support more modern GHCs more directly, and include nonmoving gc stats. ([#53](https://github.com/haskell-github-trust/ekg-core/pull/53))
+
 ## 0.1.1.7 (2019-03-15)
 
  * Fix two bugs in `cbits` relating to distribution values
diff --git a/System/Metrics.hs b/System/Metrics.hs
--- a/System/Metrics.hs
+++ b/System/Metrics.hs
@@ -198,14 +198,14 @@
          -> IO ()
 register name sample store = do
     atomicModifyIORef (storeState store) $ \ state@State{..} ->
-        case M.member name stateMetrics of
-            False -> let !state' = state {
+        if M.member name stateMetrics
+            then alreadyInUseError name
+            else let !state' = state {
                                stateMetrics = M.insert name
                                               (Left sample)
                                               stateMetrics
                              }
                      in (state', ())
-            True  -> alreadyInUseError name
 
 -- | Raise an exception indicating that the metric name is already in
 -- use.
@@ -331,16 +331,6 @@
 -- easily be added to a metrics store by calling their register
 -- function.
 
-#if MIN_VERSION_base(4,10,0)
--- | Convert nanoseconds to milliseconds.
-nsToMs :: Int64 -> Int64
-nsToMs s = round (realToFrac s / (1000000.0 :: Double))
-#else
--- | Convert seconds to milliseconds.
-sToMs :: Double -> Int64
-sToMs s = round (s * 1000.0)
-#endif
-
 -- | Register a number of metrics related to garbage collector
 -- behavior.
 --
@@ -398,6 +388,10 @@
 --
 -- [@rts.gc.max_bytes_used@] Maximum number of live bytes seen so far
 --
+-- [@rts.gc.max_large_bytes_used@] Maximum number of live bytes seen so far just in large ojects
+--
+-- [@rts.gc.max_compact_bytes_used@] Maximum number of live bytes seen so far just in compact regions
+--
 -- [@rts.gc.current_bytes_used@] Current number of live bytes
 --
 -- [@rts.gc.current_bytes_slop@] Current number of bytes lost to slop
@@ -418,9 +412,24 @@
 -- the most active GC thread each GC. The ratio of
 -- @par_tot_bytes_copied@ divided by @par_max_bytes_copied@ approaches
 -- 1 for a maximally sequential run and approaches the number of
--- threads (set by the RTS flag @-N@) for a maximally parallel run.
+-- threads (set by the RTS flag @-N@) for a maximally parallel run. Deprecated by
+-- GHC in later versions.
+--
+-- [@rts.gc.par_balanced_bytes_copied@] Sum of balanced data copied by all threads in parallel GC, across all parallel GCs.
+--
+-- [@rts.gc.nm.sync_cpu_ms@] The total CPU time used during the post-mark pause phase of the concurrent nonmoving GC.
+--
+-- [@rts.gc.nm.sync_elapsed_ms@] The total time elapsed during the post-mark pause phase of the concurrent nonmoving GC.
+--
+-- [@rts.gc.nm.sync_max_elapsed_ms@] The maximum elapsed length of any post-mark pause phase of the concurrent nonmoving GC.
+--
+-- [@rts.gc.nm.cpu_ms@] The total CPU time used by the nonmoving GC.
+--
+-- [@rts.gc.nm.elapsed_ms@] The total time elapsed during which there is a nonmoving GC active.
+--
+-- [@rts.gc.nm.max_elapsed_ms@] The maximum time elapsed during any nonmoving GC cycle.
 registerGcMetrics :: Store -> IO ()
-registerGcMetrics store =
+registerGcMetrics =
     registerGroup
 #if MIN_VERSION_base(4,10,0)
     (M.fromList
@@ -440,6 +449,8 @@
      , ("rts.gc.cpu_ms"                   , Counter . nsToMs . Stats.cpu_ns)
      , ("rts.gc.wall_ms"                  , Counter . nsToMs . Stats.elapsed_ns)
      , ("rts.gc.max_bytes_used"           , Gauge . fromIntegral . Stats.max_live_bytes)
+     , ("rts.gc.max_large_bytes_used"     , Gauge . fromIntegral . Stats.max_large_objects_bytes)
+     , ("rts.gc.max_compact_bytes_used"   , Gauge . fromIntegral . Stats.max_compact_bytes)
      , ("rts.gc.current_bytes_used"       , Gauge . fromIntegral . Stats.gcdetails_live_bytes . Stats.gc)
      , ("rts.gc.current_bytes_slop"       , Gauge . fromIntegral . Stats.gcdetails_slop_bytes . Stats.gc)
      , ("rts.gc.max_bytes_slop"           , Gauge . fromIntegral . Stats.max_slop_bytes)
@@ -447,8 +458,23 @@
      , ("rts.gc.par_tot_bytes_copied"     , Gauge . fromIntegral . Stats.par_copied_bytes)
      , ("rts.gc.par_avg_bytes_copied"     , Gauge . fromIntegral . Stats.par_copied_bytes)
      , ("rts.gc.par_max_bytes_copied"     , Gauge . fromIntegral . Stats.cumulative_par_max_copied_bytes)
+#if MIN_VERSION_base(4,11,0)
+     , ("rts.gc.par_balanced_bytes_copied", Gauge . fromIntegral . Stats.cumulative_par_balanced_copied_bytes)
+#if MIN_VERSION_base(4,15,0)
+     , ("rts.gc.nm.sync_cpu_ms"           , Counter . nsToMs . Stats.nonmoving_gc_sync_cpu_ns)
+     , ("rts.gc.nm.sync_elapsed_ms"       , Counter . nsToMs . Stats.nonmoving_gc_sync_elapsed_ns)
+     , ("rts.gc.nm.sync_max_elapsed_ms"   , Counter . nsToMs . Stats.nonmoving_gc_sync_max_elapsed_ns)
+     , ("rts.gc.nm.cpu_ms"                , Counter . nsToMs . Stats.nonmoving_gc_cpu_ns)
+     , ("rts.gc.nm.elapsed_ms"            , Counter . nsToMs . Stats.nonmoving_gc_elapsed_ns)
+     , ("rts.gc.nm.max_elapsed_ms"        , Counter . nsToMs . Stats.nonmoving_gc_max_elapsed_ns)
+# endif
+# endif
      ])
     getRTSStats
+    where
+    -- | Convert nanoseconds to milliseconds.
+    nsToMs :: Int64 -> Int64
+    nsToMs s = round (realToFrac s / (1000000.0 :: Double))
 #else
     (M.fromList
      [ ("rts.gc.bytes_allocated"          , Counter . Stats.bytesAllocated)
@@ -472,8 +498,11 @@
      , ("rts.gc.par_max_bytes_copied"     , Gauge . Stats.parMaxBytesCopied)
      ])
     getGcStats
+    where
+    -- | Convert seconds to milliseconds.
+    sToMs :: Double -> Int64
+    sToMs s = round (s * 1000.0)
 #endif
-    store
 
 #if MIN_VERSION_base(4,10,0)
 -- | Get RTS statistics.
@@ -504,8 +533,16 @@
 # if MIN_VERSION_base(4,12,0)
     , init_cpu_ns                          = 0
     , init_elapsed_ns                      = 0
+# if MIN_VERSION_base(4,15,0)
+    , nonmoving_gc_sync_cpu_ns             = 0
+    , nonmoving_gc_sync_elapsed_ns         = 0
+    , nonmoving_gc_sync_max_elapsed_ns     = 0
+    , nonmoving_gc_cpu_ns                  = 0
+    , nonmoving_gc_elapsed_ns              = 0
+    , nonmoving_gc_max_elapsed_ns          = 0
 # endif
 # endif
+# endif
     , mutator_cpu_ns                       = 0
     , mutator_elapsed_ns                   = 0
     , gc_cpu_ns                            = 0
@@ -529,6 +566,13 @@
     , gcdetails_par_max_copied_bytes      = 0
 # if MIN_VERSION_base(4,11,0)
     , gcdetails_par_balanced_copied_bytes = 0
+# if MIN_VERSION_base(4,15,0)
+    , gcdetails_nonmoving_gc_sync_cpu_ns  = 0
+    , gcdetails_nonmoving_gc_sync_elapsed_ns = 0
+# if MIN_VERSION_base(4,18,0)
+    , gcdetails_block_fragmentation_bytes = 0
+# endif
+# endif
 # endif
     , gcdetails_sync_elapsed_ns           = 0
     , gcdetails_cpu_ns                    = 0
diff --git a/ekg-core.cabal b/ekg-core.cabal
--- a/ekg-core.cabal
+++ b/ekg-core.cabal
@@ -1,23 +1,35 @@
-cabal-version:       1.18
-name:                ekg-core
-version:             0.1.1.7
-synopsis:            Tracking of system metrics
-description:
-  This library lets you defined and track system metrics.
-homepage:            https://github.com/tibbe/ekg-core
-bug-reports:         https://github.com/tibbe/ekg-core/issues
-license:             BSD3
-license-file:        LICENSE
-author:              Johan Tibell
-maintainer:          Johan Tibell <johan.tibell@gmail.com>,
-                     Mikhail Glushenkov <mikhail.glushenkov@gmail.com>
-category:            System
-build-type:          Simple
-extra-source-files:  CHANGES.md
-tested-with:         GHC == 8.8.3, GHC == 8.6.5, GHC == 8.4.4,
-                     GHC == 8.2.2, GHC == 8.0.2, GHC == 7.10.3,
-                     GHC == 7.8.4, GHC == 7.6.3
+cabal-version:      1.18
+name:               ekg-core
+version:            0.1.1.8
+synopsis:           Tracking of system metrics
+description:        This library lets you defined and track system metrics.
+homepage:           https://github.com/tibbe/ekg-core
+bug-reports:        https://github.com/tibbe/ekg-core/issues
+license:            BSD3
+license-file:       LICENSE
+author:             Johan Tibell
+maintainer:
+  Johan Tibell <johan.tibell@gmail.com>,
+  Mikhail Glushenkov <mikhail.glushenkov@gmail.com>
 
+category:           System
+build-type:         Simple
+extra-source-files: CHANGES.md
+tested-with:
+  GHC ==8.0.2
+   || ==8.2.2
+   || ==8.4.4
+   || ==8.6.5
+   || ==8.8.3
+   || ==8.10.7
+   || ==9.0.2
+   || ==9.2.8
+   || ==9.4.8
+   || ==9.6.4
+   || ==9.6.6
+   || ==9.8.2
+   || ==9.10.1
+
 library
   exposed-modules:
     System.Metrics
@@ -33,41 +45,45 @@
     System.Metrics.ThreadId
 
   build-depends:
-    ghc-prim < 0.6,
-    base >= 4.6 && < 4.14,
-    containers >= 0.5 && < 0.7,
-    text < 1.3,
-    unordered-containers < 0.3
+      base                  >=4.6 && <4.21
+    , containers            >=0.5 && <0.8
+    , text                  <2.2
+    , unordered-containers  <0.3
 
-  default-language:    Haskell2010
+  default-language: Haskell2010
+  ghc-options:      -Wall
 
-  ghc-options: -Wall
   if arch(i386)
     cc-options: -march=i686
-  includes: distrib.h
+
+  includes:         distrib.h
   install-includes: distrib.h
-  include-dirs: cbits
-  c-sources: cbits/atomic.c cbits/distrib.c
+  include-dirs:     cbits
+  c-sources:
+    cbits/atomic.c
+    cbits/distrib.c
 
 benchmark counter
-  main-is: Counter.hs
-  type: exitcode-stdio-1.0
+  main-is:          Counter.hs
+  type:             exitcode-stdio-1.0
   build-depends:
-    base,
-    ekg-core
+      base
+    , ekg-core
+
   default-language: Haskell2010
-  hs-source-dirs: benchmarks
-  ghc-options: -O2 -threaded -Wall
+  hs-source-dirs:   benchmarks
+  ghc-options:      -O2 -threaded -Wall
 
 benchmark distribution
-  main-is: Distribution.hs
-  type: exitcode-stdio-1.0
+  main-is:          Distribution.hs
+  type:             exitcode-stdio-1.0
   build-depends:
-    base,
-    ekg-core
+      base
+    , ekg-core
+
   default-language: Haskell2010
-  hs-source-dirs: benchmarks
-  ghc-options: -O2 -threaded -Wall
+  hs-source-dirs:   benchmarks
+  ghc-options:      -O2 -threaded -Wall
 
 source-repository head
   type:     git
