{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StrictData #-}

{- |
Module      :  OpenTelemetry.Attributes
Copyright   :  (c) Ian Duncan, 2021-2026
License     :  BSD-3
Description :  Key-value pair metadata for spans, events, links, and resources
Stability   :  experimental

= Overview

Attributes are key-value pairs attached to spans, events, links, and
resources. Keys are 'Text' strings; values are one of the OpenTelemetry
primitive types: 'Text', 'Bool', 'Int64', 'Double', or arrays thereof.

= Quick example

@
import OpenTelemetry.Attributes

-- On a span:
addAttribute span "http.request.method" (toAttribute "GET")
addAttribute span "http.response.status_code" (toAttribute (200 :: Int))
addAttributes span
  [ ("user.id", toAttribute "abc123")
  , ("user.role", toAttribute "admin")
  ]

-- Using the builder API:
let attrs = buildAttrs $
      attr "http.request.method" ("GET" :: Text)
      <> attr "http.response.status_code" (200 :: Int)
@

= Typed attribute keys

For type-safe attribute access, use 'AttributeKey':

@
import OpenTelemetry.Attributes.Key (AttributeKey(..), unkey)
import qualified OpenTelemetry.SemanticConventions as SC

let attrs' = addAttributeByKey defaultAttributeLimits attrs SC.http_request_method "GET"
lookupAttributeByKey attrs' SC.http_response_statusCode  -- Maybe Int64
@

= Attribute limits

The SDK enforces limits on attribute count and value length, configured via
@OTEL_ATTRIBUTE_COUNT_LIMIT@ and @OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT@
environment variables. When limits are exceeded, attributes are dropped
(tracked by 'getDropped').

= Spec reference

<https://opentelemetry.io/docs/specs/otel/common/#attribute>
-}
module OpenTelemetry.Attributes (
  Attributes,
  emptyAttributes,
  unsafeAttributesFromMap,
  addAttribute,
  addAttributeByKey,
  addAttributes,
  addAttributesFromBuilder,
  lookupAttribute,
  lookupAttributeByKey,
  getAttributeMap,
  getCount,
  getDropped,
  Attribute (..),
  ToAttribute (..),
  FromAttribute (..),
  PrimitiveAttribute (..),
  ToPrimitiveAttribute (..),
  FromPrimitiveAttribute (..),
  Map.AttributeMap,
  AttributeKey (..),
  module Key,

  -- * Attribute builder
  AttrsBuilder,
  attr,
  optAttr,
  (.@),
  (.@?),
  buildAttrs,

  -- * Attribute limits
  AttributeLimits (..),
  defaultAttributeLimits,

  -- * Unsafe utilities
  unsafeAttributesFromListIgnoringLimits,
  unsafeAttributesFromMapIgnoringLimits,
  unsafeMergeAttributesIgnoringLimits,
) where

import Data.Data (Data)
import qualified Data.HashMap.Lazy as H
import Data.Hashable (Hashable)
import Data.Maybe (isJust)
import Data.Text (Text)
import qualified Data.Text as T
import GHC.Generics (Generic)
import qualified Language.Haskell.TH.Syntax as TH
import OpenTelemetry.Attributes.Attribute (Attribute (..), FromAttribute (..), FromPrimitiveAttribute (..), PrimitiveAttribute (..), ToAttribute (..), ToPrimitiveAttribute (..))
import OpenTelemetry.Attributes.Key as Key
import qualified OpenTelemetry.Attributes.Map as Map


{- | Default attribute limits used in the global attribute limit configuration if no environment variables are set.

 Values:

 - 'attributeCountLimit': @Just 128@
 - 'attributeLengthLimit':  or @Nothing@

@since 0.0.1.0
-}
defaultAttributeLimits :: AttributeLimits
defaultAttributeLimits :: AttributeLimits
defaultAttributeLimits =
  AttributeLimits
    { attributeCountLimit :: Maybe Int
attributeCountLimit = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
128
    , attributeLengthLimit :: Maybe Int
attributeLengthLimit = Maybe Int
forall a. Maybe a
Nothing
    }


-- | @since 0.0.1.0
data Attributes = Attributes
  { Attributes -> AttributeMap
attributeMap :: !Map.AttributeMap
  , Attributes -> Int
attributesCount :: {-# UNPACK #-} !Int
  , Attributes -> Int
attributesDropped :: {-# UNPACK #-} !Int
  }
  deriving stock (Int -> Attributes -> ShowS
[Attributes] -> ShowS
Attributes -> String
(Int -> Attributes -> ShowS)
-> (Attributes -> String)
-> ([Attributes] -> ShowS)
-> Show Attributes
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Attributes -> ShowS
showsPrec :: Int -> Attributes -> ShowS
$cshow :: Attributes -> String
show :: Attributes -> String
$cshowList :: [Attributes] -> ShowS
showList :: [Attributes] -> ShowS
Show, (forall x. Attributes -> Rep Attributes x)
-> (forall x. Rep Attributes x -> Attributes) -> Generic Attributes
forall x. Rep Attributes x -> Attributes
forall x. Attributes -> Rep Attributes x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Attributes -> Rep Attributes x
from :: forall x. Attributes -> Rep Attributes x
$cto :: forall x. Rep Attributes x -> Attributes
to :: forall x. Rep Attributes x -> Attributes
Generic, Attributes -> Attributes -> Bool
(Attributes -> Attributes -> Bool)
-> (Attributes -> Attributes -> Bool) -> Eq Attributes
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Attributes -> Attributes -> Bool
== :: Attributes -> Attributes -> Bool
$c/= :: Attributes -> Attributes -> Bool
/= :: Attributes -> Attributes -> Bool
Eq, Eq Attributes
Eq Attributes =>
(Attributes -> Attributes -> Ordering)
-> (Attributes -> Attributes -> Bool)
-> (Attributes -> Attributes -> Bool)
-> (Attributes -> Attributes -> Bool)
-> (Attributes -> Attributes -> Bool)
-> (Attributes -> Attributes -> Attributes)
-> (Attributes -> Attributes -> Attributes)
-> Ord Attributes
Attributes -> Attributes -> Bool
Attributes -> Attributes -> Ordering
Attributes -> Attributes -> Attributes
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Attributes -> Attributes -> Ordering
compare :: Attributes -> Attributes -> Ordering
$c< :: Attributes -> Attributes -> Bool
< :: Attributes -> Attributes -> Bool
$c<= :: Attributes -> Attributes -> Bool
<= :: Attributes -> Attributes -> Bool
$c> :: Attributes -> Attributes -> Bool
> :: Attributes -> Attributes -> Bool
$c>= :: Attributes -> Attributes -> Bool
>= :: Attributes -> Attributes -> Bool
$cmax :: Attributes -> Attributes -> Attributes
max :: Attributes -> Attributes -> Attributes
$cmin :: Attributes -> Attributes -> Attributes
min :: Attributes -> Attributes -> Attributes
Ord, (forall (m :: * -> *). Quote m => Attributes -> m Exp)
-> (forall (m :: * -> *).
    Quote m =>
    Attributes -> Code m Attributes)
-> Lift Attributes
forall t.
(forall (m :: * -> *). Quote m => t -> m Exp)
-> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
forall (m :: * -> *). Quote m => Attributes -> m Exp
forall (m :: * -> *). Quote m => Attributes -> Code m Attributes
$clift :: forall (m :: * -> *). Quote m => Attributes -> m Exp
lift :: forall (m :: * -> *). Quote m => Attributes -> m Exp
$cliftTyped :: forall (m :: * -> *). Quote m => Attributes -> Code m Attributes
liftTyped :: forall (m :: * -> *). Quote m => Attributes -> Code m Attributes
TH.Lift)


instance Hashable Attributes


-- | @since 0.0.1.0
emptyAttributes :: Attributes
emptyAttributes :: Attributes
emptyAttributes = AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
forall a. Monoid a => a
mempty Int
0 Int
0
{-# INLINE emptyAttributes #-}


{- | Build 'Attributes' directly from a pre-built 'AttributeMap', applying
count and length limits. Faster than @addAttributes limits emptyAttributes map@
because it skips the per-key membership check against an empty base map.

@since 0.4.0.0
-}
unsafeAttributesFromMap :: AttributeLimits -> Map.AttributeMap -> Attributes
unsafeAttributesFromMap :: AttributeLimits -> AttributeMap -> Attributes
unsafeAttributesFromMap AttributeLimits {Maybe Int
attributeCountLimit :: AttributeLimits -> Maybe Int
attributeLengthLimit :: AttributeLimits -> Maybe Int
attributeCountLimit :: Maybe Int
attributeLengthLimit :: Maybe Int
..} AttributeMap
m =
  let limitVal :: Attribute -> Attribute
limitVal = case Maybe Int
attributeLengthLimit of
        Maybe Int
Nothing -> Attribute -> Attribute
forall a. a -> a
id
        Just Int
limit -> Int -> Attribute -> Attribute
limitLengths Int
limit
  in case Maybe Int
attributeCountLimit of
       Maybe Int
Nothing ->
         let !m' :: AttributeMap
m' = case Maybe Int
attributeLengthLimit of
               Maybe Int
Nothing -> AttributeMap
m
               Just Int
_ -> (Attribute -> Attribute) -> AttributeMap -> AttributeMap
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
H.map Attribute -> Attribute
limitVal AttributeMap
m
         in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
m' (AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
m) Int
0
       Just Int
limit_ ->
         let !sz :: Int
sz = AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
m
         in if Int
sz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
limit_
              then
                let !m' :: AttributeMap
m' = case Maybe Int
attributeLengthLimit of
                      Maybe Int
Nothing -> AttributeMap
m
                      Just Int
_ -> (Attribute -> Attribute) -> AttributeMap -> AttributeMap
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
H.map Attribute -> Attribute
limitVal AttributeMap
m
                in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
m' Int
sz Int
0
              else
                let (!AttributeMap
kept, !Int
dropped) =
                      ((AttributeMap, Int) -> Text -> Attribute -> (AttributeMap, Int))
-> (AttributeMap, Int) -> AttributeMap -> (AttributeMap, Int)
forall a k v. (a -> k -> v -> a) -> a -> HashMap k v -> a
H.foldlWithKey'
                        ( \(!AttributeMap
acc, !Int
d) Text
k Attribute
v ->
                            if AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
acc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
limit_
                              then (Text -> Attribute -> AttributeMap -> AttributeMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert Text
k (Attribute -> Attribute
limitVal Attribute
v) AttributeMap
acc, Int
d)
                              else (AttributeMap
acc, Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                        )
                        (AttributeMap
forall k v. HashMap k v
H.empty, Int
0)
                        AttributeMap
m
                in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
kept (AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
kept) Int
dropped
{-# INLINE unsafeAttributesFromMap #-}


-- | @since 0.0.1.0
addAttribute :: (ToAttribute a) => AttributeLimits -> Attributes -> Text -> a -> Attributes
addAttribute :: forall a.
ToAttribute a =>
AttributeLimits -> Attributes -> Text -> a -> Attributes
addAttribute AttributeLimits {Maybe Int
attributeCountLimit :: AttributeLimits -> Maybe Int
attributeLengthLimit :: AttributeLimits -> Maybe Int
attributeCountLimit :: Maybe Int
attributeLengthLimit :: Maybe Int
..} Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} !Text
k a
v =
  let attr :: Attribute
attr = case Maybe Int
attributeLengthLimit of
        Maybe Int
Nothing -> a -> Attribute
forall a. ToAttribute a => a -> Attribute
toAttribute a
v
        Just Int
limit -> Int -> Attribute -> Attribute
limitLengths Int
limit (a -> Attribute
forall a. ToAttribute a => a -> Attribute
toAttribute a
v)
      (!Bool
replacing, !AttributeMap
newAttrs) = (Maybe Attribute -> (Bool, Maybe Attribute))
-> Text -> AttributeMap -> (Bool, AttributeMap)
forall (f :: * -> *) k v.
(Functor f, Eq k, Hashable k) =>
(Maybe v -> f (Maybe v)) -> k -> HashMap k v -> f (HashMap k v)
H.alterF (\Maybe Attribute
old -> (Maybe Attribute -> Bool
forall a. Maybe a -> Bool
isJust Maybe Attribute
old, Attribute -> Maybe Attribute
forall a. a -> Maybe a
Just Attribute
attr)) Text
k AttributeMap
attributeMap
      !newCount :: Int
newCount = if Bool
replacing then Int
attributesCount else Int
attributesCount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  in case Maybe Int
attributeCountLimit of
       Maybe Int
Nothing -> AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
newAttrs Int
newCount Int
attributesDropped
       Just Int
limit_ ->
         if Bool -> Bool
not Bool
replacing Bool -> Bool -> Bool
&& Int
newCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
limit_
           then AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
attributeMap Int
attributesCount (Int
attributesDropped Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
           else AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
newAttrs Int
newCount Int
attributesDropped
{-# INLINE [0] addAttribute #-}


-- | @since 0.0.1.0
addAttributeByKey :: (ToAttribute a) => AttributeLimits -> Attributes -> AttributeKey a -> a -> Attributes
addAttributeByKey :: forall a.
ToAttribute a =>
AttributeLimits -> Attributes -> AttributeKey a -> a -> Attributes
addAttributeByKey AttributeLimits
limits Attributes
attrs (AttributeKey Text
k) a
v = AttributeLimits -> Attributes -> Text -> a -> Attributes
forall a.
ToAttribute a =>
AttributeLimits -> Attributes -> Text -> a -> Attributes
addAttribute AttributeLimits
limits Attributes
attrs Text
k a
v
{-# INLINE addAttributeByKey #-}


-- Fuse two nested pure addAttribute calls into a single addAttributesFromBuilder pass.
-- Two H.alterF to one fold. Only fires in phases >=1 (before addAttribute inlines in phase 0).
{-# RULES
"addAttribute/addAttribute" forall lim attrs k1 v1 k2 v2.
  addAttribute lim (addAttribute lim attrs k1 v1) k2 v2 =
    addAttributesFromBuilder lim attrs (attr k1 v1 <> attr k2 v2)
  #-}


-- | @since 0.0.1.0
addAttributes :: (ToAttribute a) => AttributeLimits -> Attributes -> H.HashMap Text a -> Attributes
addAttributes :: forall a.
ToAttribute a =>
AttributeLimits -> Attributes -> HashMap Text a -> Attributes
addAttributes AttributeLimits {Maybe Int
attributeCountLimit :: AttributeLimits -> Maybe Int
attributeLengthLimit :: AttributeLimits -> Maybe Int
attributeCountLimit :: Maybe Int
attributeLengthLimit :: Maybe Int
..} Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} HashMap Text a
attrs
  | HashMap Text a -> Bool
forall k v. HashMap k v -> Bool
H.null HashMap Text a
attrs = AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
attributeMap Int
attributesCount Int
attributesDropped
  | Bool
otherwise =
      let convertVal :: a -> Attribute
convertVal = case Maybe Int
attributeLengthLimit of
            Maybe Int
Nothing -> a -> Attribute
forall a. ToAttribute a => a -> Attribute
toAttribute
            Just Int
limit -> Int -> Attribute -> Attribute
limitLengths Int
limit (Attribute -> Attribute) -> (a -> Attribute) -> a -> Attribute
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Attribute
forall a. ToAttribute a => a -> Attribute
toAttribute
      in case Maybe Int
attributeCountLimit of
           Maybe Int
Nothing ->
             let (!AttributeMap
newAttrs, !Int
added) =
                   ((AttributeMap, Int) -> Text -> a -> (AttributeMap, Int))
-> (AttributeMap, Int) -> HashMap Text a -> (AttributeMap, Int)
forall a k v. (a -> k -> v -> a) -> a -> HashMap k v -> a
H.foldlWithKey'
                     (\(!AttributeMap
m, !Int
n) Text
k a
v -> (Text -> Attribute -> AttributeMap -> AttributeMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert Text
k (a -> Attribute
convertVal a
v) AttributeMap
m, if Text -> AttributeMap -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
H.member Text
k AttributeMap
attributeMap then Int
n else Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1))
                     (AttributeMap
attributeMap, Int
0 :: Int)
                     HashMap Text a
attrs
                 !newCount :: Int
newCount = Int
attributesCount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
added
             in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
newAttrs Int
newCount Int
attributesDropped
           Just Int
limit_ ->
             let (!AttributeMap
merged, !Int
accepted, !Int
totalNew) =
                   ((AttributeMap, Int, Int) -> Text -> a -> (AttributeMap, Int, Int))
-> (AttributeMap, Int, Int)
-> HashMap Text a
-> (AttributeMap, Int, Int)
forall a k v. (a -> k -> v -> a) -> a -> HashMap k v -> a
H.foldlWithKey'
                     ( \(!AttributeMap
m, !Int
n, !Int
seen) Text
k a
v ->
                         if Text -> AttributeMap -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
H.member Text
k AttributeMap
attributeMap
                           then (Text -> Attribute -> AttributeMap -> AttributeMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert Text
k (a -> Attribute
convertVal a
v) AttributeMap
m, Int
n, Int
seen)
                           else
                             if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
limit_
                               then (Text -> Attribute -> AttributeMap -> AttributeMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert Text
k (a -> Attribute
convertVal a
v) AttributeMap
m, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, Int
seen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                               else (AttributeMap
m, Int
n, Int
seen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                     )
                     (AttributeMap
attributeMap, Int
attributesCount, Int
0 :: Int)
                     HashMap Text a
attrs
                 !newKeys :: Int
newKeys = Int
accepted Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
attributesCount
                 !dropped :: Int
dropped = Int
totalNew Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
newKeys
             in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
merged Int
accepted (Int
attributesDropped Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dropped)
{-# INLINE addAttributes #-}


{- | Like 'addAttributes', but consumes an 'AttrsBuilder' instead of a 'HashMap'.
Folds each attribute directly into the existing 'Attributes' without allocating
an intermediate collection.

@since 0.4.0.0
-}
addAttributesFromBuilder :: AttributeLimits -> Attributes -> AttrsBuilder -> Attributes
addAttributesFromBuilder :: AttributeLimits -> Attributes -> AttrsBuilder -> Attributes
addAttributesFromBuilder AttributeLimits {Maybe Int
attributeCountLimit :: AttributeLimits -> Maybe Int
attributeLengthLimit :: AttributeLimits -> Maybe Int
attributeCountLimit :: Maybe Int
attributeLengthLimit :: Maybe Int
..} _as :: Attributes
_as@Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} (AttrsBuilder forall r. (r -> Text -> Attribute -> r) -> r -> r
fold) =
  let limitVal :: Attribute -> Attribute
limitVal = case Maybe Int
attributeLengthLimit of
        Maybe Int
Nothing -> Attribute -> Attribute
forall a. a -> a
id
        Just Int
limit -> Int -> Attribute -> Attribute
limitLengths Int
limit
  in case Maybe Int
attributeCountLimit of
       Maybe Int
Nothing ->
         let (!AttributeMap
newMap, !Int
added) = ((AttributeMap, Int) -> Text -> Attribute -> (AttributeMap, Int))
-> (AttributeMap, Int) -> (AttributeMap, Int)
forall r. (r -> Text -> Attribute -> r) -> r -> r
fold (\(!AttributeMap
m, !Int
n) Text
k Attribute
v -> (Text -> Attribute -> AttributeMap -> AttributeMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert Text
k (Attribute -> Attribute
limitVal Attribute
v) AttributeMap
m, if Text -> AttributeMap -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
H.member Text
k AttributeMap
m then Int
n else Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) (AttributeMap
attributeMap, Int
0 :: Int)
             !newCount :: Int
newCount = Int
attributesCount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
added
         in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
newMap Int
newCount Int
attributesDropped
       Just Int
limit_ ->
         let step :: (HashMap k Attribute, Int, c)
-> k -> Attribute -> (HashMap k Attribute, Int, c)
step (!HashMap k Attribute
m, !Int
cnt, !c
drp) !k
k Attribute
v =
               let a :: Attribute
a = Attribute -> Attribute
limitVal Attribute
v
               in if k -> HashMap k Attribute -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
H.member k
k HashMap k Attribute
m
                    then (k -> Attribute -> HashMap k Attribute -> HashMap k Attribute
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert k
k Attribute
a HashMap k Attribute
m, Int
cnt, c
drp)
                    else
                      if Int
cnt Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
limit_
                        then (k -> Attribute -> HashMap k Attribute -> HashMap k Attribute
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert k
k Attribute
a HashMap k Attribute
m, Int
cnt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, c
drp)
                        else (HashMap k Attribute
m, Int
cnt, c
drp c -> c -> c
forall a. Num a => a -> a -> a
+ c
1)
             (!AttributeMap
newMap, !Int
newCount, !Int
newDropped) = ((AttributeMap, Int, Int)
 -> Text -> Attribute -> (AttributeMap, Int, Int))
-> (AttributeMap, Int, Int) -> (AttributeMap, Int, Int)
forall r. (r -> Text -> Attribute -> r) -> r -> r
fold (AttributeMap, Int, Int)
-> Text -> Attribute -> (AttributeMap, Int, Int)
forall {k} {c}.
(Hashable k, Num c) =>
(HashMap k Attribute, Int, c)
-> k -> Attribute -> (HashMap k Attribute, Int, c)
step (AttributeMap
attributeMap, Int
attributesCount, Int
attributesDropped)
         in AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
newMap Int
newCount Int
newDropped
{-# INLINE addAttributesFromBuilder #-}


-- Eliminate no-ops at compile time.
{-# RULES
"addAttributesFromBuilder/mempty" forall lim attrs.
  addAttributesFromBuilder lim attrs mempty =
    attrs
  #-}


{- | Church-encoded left fold over attribute key-value pairs. Avoids allocating
intermediate tuples, list spines, or 'HashMap's when adding multiple
attributes to a span.

Construct individual entries with 'attr' \/ '.@' and combine with '<>'.
GHC can inline and fuse static builder expressions, eliminating all
intermediate allocation.

@
'addAttributes'' span $
    SC.http_request_method '.@' method
 <> SC.url_full '.@' url
 <> SC.server_port '.@?' mPort
@

@since 0.4.0.0
-}
newtype AttrsBuilder = AttrsBuilder (forall r. (r -> Text -> Attribute -> r) -> r -> r)


instance Semigroup AttrsBuilder where
  AttrsBuilder forall r. (r -> Text -> Attribute -> r) -> r -> r
f <> :: AttrsBuilder -> AttrsBuilder -> AttrsBuilder
<> AttrsBuilder forall r. (r -> Text -> Attribute -> r) -> r -> r
g = (forall r. (r -> Text -> Attribute -> r) -> r -> r) -> AttrsBuilder
AttrsBuilder (\r -> Text -> Attribute -> r
step r
z -> (r -> Text -> Attribute -> r) -> r -> r
forall r. (r -> Text -> Attribute -> r) -> r -> r
g r -> Text -> Attribute -> r
step ((r -> Text -> Attribute -> r) -> r -> r
forall r. (r -> Text -> Attribute -> r) -> r -> r
f r -> Text -> Attribute -> r
step r
z))
  {-# INLINE (<>) #-}


instance Monoid AttrsBuilder where
  mempty :: AttrsBuilder
mempty = (forall r. (r -> Text -> Attribute -> r) -> r -> r) -> AttrsBuilder
AttrsBuilder (\r -> Text -> Attribute -> r
_ r
z -> r
z)
  {-# INLINE mempty #-}


{- | Build an attribute entry from a 'Text' key. The value is converted
to 'Attribute' lazily; actual conversion is deferred until the exporter
thread reads the attribute, keeping the instrumented thread fast.

@since 0.4.0.0
-}
attr :: (ToAttribute a) => Text -> a -> AttrsBuilder
attr :: forall a. ToAttribute a => Text -> a -> AttrsBuilder
attr !Text
k a
v = let a :: Attribute
a = a -> Attribute
forall a. ToAttribute a => a -> Attribute
toAttribute a
v in (forall r. (r -> Text -> Attribute -> r) -> r -> r) -> AttrsBuilder
AttrsBuilder (\r -> Text -> Attribute -> r
step r
z -> r -> Text -> Attribute -> r
step r
z Text
k Attribute
a)
{-# INLINE attr #-}


{- | Build an optional attribute entry. 'Nothing' contributes nothing
to the builder (zero cost).

@since 0.4.0.0
-}
optAttr :: (ToAttribute a) => Text -> Maybe a -> AttrsBuilder
optAttr :: forall a. ToAttribute a => Text -> Maybe a -> AttrsBuilder
optAttr Text
_ Maybe a
Nothing = AttrsBuilder
forall a. Monoid a => a
mempty
optAttr !Text
k (Just a
v) = Text -> a -> AttrsBuilder
forall a. ToAttribute a => Text -> a -> AttrsBuilder
attr Text
k a
v
{-# INLINE optAttr #-}


{- | Build an attribute entry from a typed 'AttributeKey'. Type-safe:
the value type must match the key's phantom type.

@
SC.http_request_method '.@' ("GET" :: Text)
@

@since 0.4.0.0
-}
(.@) :: (ToAttribute a) => AttributeKey a -> a -> AttrsBuilder
(AttributeKey !Text
k) .@ :: forall a. ToAttribute a => AttributeKey a -> a -> AttrsBuilder
.@ a
v = Text -> a -> AttrsBuilder
forall a. ToAttribute a => Text -> a -> AttrsBuilder
attr Text
k a
v
{-# INLINE (.@) #-}


infixl 8 .@


{- | Build an optional attribute entry from a typed 'AttributeKey'.
'Nothing' contributes nothing to the builder.

@since 0.4.0.0
-}
(.@?) :: (ToAttribute a) => AttributeKey a -> Maybe a -> AttrsBuilder
AttributeKey a
_ .@? :: forall a.
ToAttribute a =>
AttributeKey a -> Maybe a -> AttrsBuilder
.@? Maybe a
Nothing = AttrsBuilder
forall a. Monoid a => a
mempty
(AttributeKey !Text
k) .@? (Just a
v) = Text -> a -> AttrsBuilder
forall a. ToAttribute a => Text -> a -> AttrsBuilder
attr Text
k a
v
{-# INLINE (.@?) #-}


infixl 8 .@?


{- | Materialize a builder into an 'Map.AttributeMap'. Useful when a raw
'HashMap' is needed (e.g. for 'NewEvent' attributes or 'SpanArguments').

@since 0.4.0.0
-}
buildAttrs :: AttrsBuilder -> Map.AttributeMap
buildAttrs :: AttrsBuilder -> AttributeMap
buildAttrs (AttrsBuilder forall r. (r -> Text -> Attribute -> r) -> r -> r
f) = (AttributeMap -> Text -> Attribute -> AttributeMap)
-> AttributeMap -> AttributeMap
forall r. (r -> Text -> Attribute -> r) -> r -> r
f (\AttributeMap
m Text
k Attribute
v -> Text -> Attribute -> AttributeMap -> AttributeMap
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
H.insert Text
k Attribute
v AttributeMap
m) AttributeMap
forall k v. HashMap k v
H.empty
{-# INLINE buildAttrs #-}


limitPrimAttr :: Int -> PrimitiveAttribute -> PrimitiveAttribute
limitPrimAttr :: Int -> PrimitiveAttribute -> PrimitiveAttribute
limitPrimAttr Int
limit (TextAttribute Text
t) = Text -> PrimitiveAttribute
TextAttribute (Int -> Text -> Text
T.take Int
limit Text
t)
limitPrimAttr Int
_ PrimitiveAttribute
attr = PrimitiveAttribute
attr


limitLengths :: Int -> Attribute -> Attribute
limitLengths :: Int -> Attribute -> Attribute
limitLengths Int
limit (AttributeValue PrimitiveAttribute
val) = PrimitiveAttribute -> Attribute
AttributeValue (PrimitiveAttribute -> Attribute)
-> PrimitiveAttribute -> Attribute
forall a b. (a -> b) -> a -> b
$ Int -> PrimitiveAttribute -> PrimitiveAttribute
limitPrimAttr Int
limit PrimitiveAttribute
val
limitLengths Int
limit (AttributeArray [PrimitiveAttribute]
arr) = [PrimitiveAttribute] -> Attribute
AttributeArray ([PrimitiveAttribute] -> Attribute)
-> [PrimitiveAttribute] -> Attribute
forall a b. (a -> b) -> a -> b
$ (PrimitiveAttribute -> PrimitiveAttribute)
-> [PrimitiveAttribute] -> [PrimitiveAttribute]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> PrimitiveAttribute -> PrimitiveAttribute
limitPrimAttr Int
limit) [PrimitiveAttribute]
arr


-- | @since 0.0.1.0
getAttributeMap :: Attributes -> Map.AttributeMap
getAttributeMap :: Attributes -> AttributeMap
getAttributeMap Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} = AttributeMap
attributeMap
{-# INLINE getAttributeMap #-}


-- | @since 0.0.1.0
getCount :: Attributes -> Int
getCount :: Attributes -> Int
getCount Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} = Int
attributesCount
{-# INLINE getCount #-}


-- | @since 0.0.1.0
getDropped :: Attributes -> Int
getDropped :: Attributes -> Int
getDropped Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} = Int
attributesDropped
{-# INLINE getDropped #-}


-- | @since 0.0.1.0
lookupAttribute :: Attributes -> Text -> Maybe Attribute
lookupAttribute :: Attributes -> Text -> Maybe Attribute
lookupAttribute Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} Text
k = Text -> AttributeMap -> Maybe Attribute
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
H.lookup Text
k AttributeMap
attributeMap
{-# INLINE lookupAttribute #-}


-- | @since 0.0.1.0
lookupAttributeByKey :: FromAttribute a => Attributes -> AttributeKey a -> Maybe a
lookupAttributeByKey :: forall a.
FromAttribute a =>
Attributes -> AttributeKey a -> Maybe a
lookupAttributeByKey Attributes {Int
AttributeMap
attributeMap :: Attributes -> AttributeMap
attributesCount :: Attributes -> Int
attributesDropped :: Attributes -> Int
attributeMap :: AttributeMap
attributesCount :: Int
attributesDropped :: Int
..} AttributeKey a
k = AttributeKey a -> AttributeMap -> Maybe a
forall a.
FromAttribute a =>
AttributeKey a -> AttributeMap -> Maybe a
Map.lookupByKey AttributeKey a
k AttributeMap
attributeMap
{-# INLINEABLE lookupAttributeByKey #-}


{- | It is possible when adding attributes that a programming error might cause too many
 attributes to be added to an event. Thus, 'Attributes' use the limits set here as a safeguard
 against excessive memory consumption.

@since 0.0.1.0
-}
data AttributeLimits = AttributeLimits
  { AttributeLimits -> Maybe Int
attributeCountLimit :: Maybe Int
  -- ^ The number of unique attributes that may be added to an 'Attributes' structure before they are dropped.
  , AttributeLimits -> Maybe Int
attributeLengthLimit :: Maybe Int
  {- ^ The maximum length of string attributes that may be set. Longer-length string values will be truncated to the
  specified amount.
  -}
  }
  deriving stock (ReadPrec [AttributeLimits]
ReadPrec AttributeLimits
Int -> ReadS AttributeLimits
ReadS [AttributeLimits]
(Int -> ReadS AttributeLimits)
-> ReadS [AttributeLimits]
-> ReadPrec AttributeLimits
-> ReadPrec [AttributeLimits]
-> Read AttributeLimits
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS AttributeLimits
readsPrec :: Int -> ReadS AttributeLimits
$creadList :: ReadS [AttributeLimits]
readList :: ReadS [AttributeLimits]
$creadPrec :: ReadPrec AttributeLimits
readPrec :: ReadPrec AttributeLimits
$creadListPrec :: ReadPrec [AttributeLimits]
readListPrec :: ReadPrec [AttributeLimits]
Read, Int -> AttributeLimits -> ShowS
[AttributeLimits] -> ShowS
AttributeLimits -> String
(Int -> AttributeLimits -> ShowS)
-> (AttributeLimits -> String)
-> ([AttributeLimits] -> ShowS)
-> Show AttributeLimits
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AttributeLimits -> ShowS
showsPrec :: Int -> AttributeLimits -> ShowS
$cshow :: AttributeLimits -> String
show :: AttributeLimits -> String
$cshowList :: [AttributeLimits] -> ShowS
showList :: [AttributeLimits] -> ShowS
Show, AttributeLimits -> AttributeLimits -> Bool
(AttributeLimits -> AttributeLimits -> Bool)
-> (AttributeLimits -> AttributeLimits -> Bool)
-> Eq AttributeLimits
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AttributeLimits -> AttributeLimits -> Bool
== :: AttributeLimits -> AttributeLimits -> Bool
$c/= :: AttributeLimits -> AttributeLimits -> Bool
/= :: AttributeLimits -> AttributeLimits -> Bool
Eq, Eq AttributeLimits
Eq AttributeLimits =>
(AttributeLimits -> AttributeLimits -> Ordering)
-> (AttributeLimits -> AttributeLimits -> Bool)
-> (AttributeLimits -> AttributeLimits -> Bool)
-> (AttributeLimits -> AttributeLimits -> Bool)
-> (AttributeLimits -> AttributeLimits -> Bool)
-> (AttributeLimits -> AttributeLimits -> AttributeLimits)
-> (AttributeLimits -> AttributeLimits -> AttributeLimits)
-> Ord AttributeLimits
AttributeLimits -> AttributeLimits -> Bool
AttributeLimits -> AttributeLimits -> Ordering
AttributeLimits -> AttributeLimits -> AttributeLimits
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: AttributeLimits -> AttributeLimits -> Ordering
compare :: AttributeLimits -> AttributeLimits -> Ordering
$c< :: AttributeLimits -> AttributeLimits -> Bool
< :: AttributeLimits -> AttributeLimits -> Bool
$c<= :: AttributeLimits -> AttributeLimits -> Bool
<= :: AttributeLimits -> AttributeLimits -> Bool
$c> :: AttributeLimits -> AttributeLimits -> Bool
> :: AttributeLimits -> AttributeLimits -> Bool
$c>= :: AttributeLimits -> AttributeLimits -> Bool
>= :: AttributeLimits -> AttributeLimits -> Bool
$cmax :: AttributeLimits -> AttributeLimits -> AttributeLimits
max :: AttributeLimits -> AttributeLimits -> AttributeLimits
$cmin :: AttributeLimits -> AttributeLimits -> AttributeLimits
min :: AttributeLimits -> AttributeLimits -> AttributeLimits
Ord, Typeable AttributeLimits
Typeable AttributeLimits =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> AttributeLimits -> c AttributeLimits)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c AttributeLimits)
-> (AttributeLimits -> Constr)
-> (AttributeLimits -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c AttributeLimits))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c AttributeLimits))
-> ((forall b. Data b => b -> b)
    -> AttributeLimits -> AttributeLimits)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> AttributeLimits -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> AttributeLimits -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> AttributeLimits -> m AttributeLimits)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> AttributeLimits -> m AttributeLimits)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> AttributeLimits -> m AttributeLimits)
-> Data AttributeLimits
AttributeLimits -> Constr
AttributeLimits -> DataType
(forall b. Data b => b -> b) -> AttributeLimits -> AttributeLimits
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int -> (forall d. Data d => d -> u) -> AttributeLimits -> u
forall u. (forall d. Data d => d -> u) -> AttributeLimits -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c AttributeLimits
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> AttributeLimits -> c AttributeLimits
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c AttributeLimits)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c AttributeLimits)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> AttributeLimits -> c AttributeLimits
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> AttributeLimits -> c AttributeLimits
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c AttributeLimits
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c AttributeLimits
$ctoConstr :: AttributeLimits -> Constr
toConstr :: AttributeLimits -> Constr
$cdataTypeOf :: AttributeLimits -> DataType
dataTypeOf :: AttributeLimits -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c AttributeLimits)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c AttributeLimits)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c AttributeLimits)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c AttributeLimits)
$cgmapT :: (forall b. Data b => b -> b) -> AttributeLimits -> AttributeLimits
gmapT :: (forall b. Data b => b -> b) -> AttributeLimits -> AttributeLimits
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> AttributeLimits -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> AttributeLimits -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> AttributeLimits -> [u]
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> AttributeLimits -> u
gmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> AttributeLimits -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AttributeLimits -> m AttributeLimits
Data, (forall x. AttributeLimits -> Rep AttributeLimits x)
-> (forall x. Rep AttributeLimits x -> AttributeLimits)
-> Generic AttributeLimits
forall x. Rep AttributeLimits x -> AttributeLimits
forall x. AttributeLimits -> Rep AttributeLimits x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. AttributeLimits -> Rep AttributeLimits x
from :: forall x. AttributeLimits -> Rep AttributeLimits x
$cto :: forall x. Rep AttributeLimits x -> AttributeLimits
to :: forall x. Rep AttributeLimits x -> AttributeLimits
Generic)
  deriving anyclass (Eq AttributeLimits
Eq AttributeLimits =>
(Int -> AttributeLimits -> Int)
-> (AttributeLimits -> Int) -> Hashable AttributeLimits
Int -> AttributeLimits -> Int
AttributeLimits -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> AttributeLimits -> Int
hashWithSalt :: Int -> AttributeLimits -> Int
$chash :: AttributeLimits -> Int
hash :: AttributeLimits -> Int
Hashable)


{- | Left-biased merge.

@since 0.0.1.0
-}
unsafeMergeAttributesIgnoringLimits :: Attributes -> Attributes -> Attributes
unsafeMergeAttributesIgnoringLimits :: Attributes -> Attributes -> Attributes
unsafeMergeAttributesIgnoringLimits Attributes
left Attributes
right = AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
hm Int
c Int
d
  where
    hm :: AttributeMap
hm = Attributes -> AttributeMap
attributeMap Attributes
left AttributeMap -> AttributeMap -> AttributeMap
forall a. Semigroup a => a -> a -> a
<> Attributes -> AttributeMap
attributeMap Attributes
right
    c :: Int
c = AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
hm
    d :: Int
d = Attributes -> Int
attributesDropped Attributes
left Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Attributes -> Int
attributesDropped Attributes
right


-- | @since 0.0.1.0
unsafeAttributesFromListIgnoringLimits :: [(Text, Attribute)] -> Attributes
unsafeAttributesFromListIgnoringLimits :: [(Text, Attribute)] -> Attributes
unsafeAttributesFromListIgnoringLimits [(Text, Attribute)]
l = AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
hm Int
c Int
0
  where
    hm :: AttributeMap
hm = [(Text, Attribute)] -> AttributeMap
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
H.fromList [(Text, Attribute)]
l
    c :: Int
c = AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
hm


{- | Wrap a pre-built HashMap directly into 'Attributes' with zero conversion.
No limit enforcement.  Used by 'filterAttributesByKeys' to avoid
a HashMap -> list -> HashMap roundtrip.

@since 0.0.1.0
-}
unsafeAttributesFromMapIgnoringLimits :: H.HashMap Text Attribute -> Attributes
unsafeAttributesFromMapIgnoringLimits :: AttributeMap -> Attributes
unsafeAttributesFromMapIgnoringLimits AttributeMap
m = AttributeMap -> Int -> Int -> Attributes
Attributes AttributeMap
m (AttributeMap -> Int
forall k v. HashMap k v -> Int
H.size AttributeMap
m) Int
0
{-# INLINE unsafeAttributesFromMapIgnoringLimits #-}