Skip to content

Commit 9bb87de

Browse files
committed
added entity, entity builder, and updated Resource with entites
1 parent 28861aa commit 9bb87de

File tree

3 files changed

+106
-4
lines changed

3 files changed

+106
-4
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// Copyright The OpenTelemetry Authors
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
import OpenTelemetryApi
7+
8+
public struct Entity : Codable, Hashable, Equatable {
9+
/// type : Defines the type of the Entity. MUST not change during the lifetime of the entity.
10+
/// For example: "service" or "host". This field is required and MUST not be empty for valid entities.
11+
public let type: String
12+
13+
/// id: A set of attributes that identifies the Entity.
14+
/// MUST not change during the lifetime of the Entity. The Id must contain at least one attribute.
15+
public let identifiers: [String: AttributeValue]
16+
17+
/// A set of descriptive (non-identifying) attributes of the Entity.
18+
/// MAY change over the lifetime of the entity. MAY be empty. These attributes are not part of Entity's identity.
19+
public var attributes: [String: AttributeValue]
20+
21+
22+
public static func builder(type: String) -> EntityBuilder {
23+
.init(type: type)
24+
}
25+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// Copyright The OpenTelemetry Authors
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
import OpenTelemetryApi
7+
8+
public class EntityBuilder {
9+
private var type: String
10+
private var identifiers: [String: AttributeValue] = [:]
11+
private var attributes: [String: AttributeValue] = [:]
12+
13+
internal init(type: String) {
14+
self.type = type
15+
}
16+
17+
public func with(identifiers: [String: AttributeValue]) -> Self {
18+
self.identifiers = identifiers
19+
return self
20+
}
21+
22+
public func with(attributes: [String: AttributeValue]) -> Self {
23+
self.attributes = attributes
24+
return self
25+
}
26+
27+
public func build() -> Entity {
28+
return Entity(type: type,
29+
identifiers: identifiers,
30+
attributes: attributes)
31+
}
32+
}

Sources/OpenTelemetrySdk/Resources/Resource.swift

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public struct Resource: Equatable, Hashable, Codable {
1414
/// A dictionary of labels that describe the resource.
1515
public var attributes: [String: AttributeValue]
1616

17+
public private(set) var entities : [Entity] = []
18+
1719
/// Returns a default Resource.
1820
public init() {
1921
let executableName = ProcessInfo.processInfo.processName
@@ -30,37 +32,80 @@ public struct Resource: Equatable, Hashable, Codable {
3032
)
3133
}
3234

35+
private static func mergeEntities(_ lhs: [Entity], _ rhs: [Entity]) -> [Entity] {
36+
if lhs.isEmpty {
37+
return rhs
38+
}
39+
40+
if rhs.isEmpty {
41+
return lhs
42+
}
43+
var entityMap = [String: Entity]()
44+
lhs.forEach { entityMap[$0.type] = $0 }
45+
rhs.forEach { entity in
46+
if !entityMap.contains(where: { key, _ in
47+
entity.type == key
48+
}) {
49+
entityMap[entity.type] = entity
50+
} else {
51+
if let old = entityMap[entity.type] {
52+
let new = Entity.builder(type: old.type)
53+
.with(identifiers: old.identifiers)
54+
.with(attributes: entity.attributes
55+
.merging(old.attributes) { _, old in old })
56+
.build()
57+
entityMap[entity.type] = new
58+
}
59+
}
60+
}
61+
return Array(entityMap.values)
62+
}
63+
3364
/// Returns an empty Resource.
3465
static var empty: Resource {
3566
return self.init(attributes: [String: AttributeValue]())
3667
}
3768

3869
/// Returns a Resource.
3970
/// - Parameter labels: a dictionary of labels that describe the resource.
40-
public init(attributes: [String: AttributeValue]) {
71+
public init(attributes: [String: AttributeValue], entities: [Entity] = []) {
72+
self.entities = entities
4173
if Resource.checkAttributes(attributes: attributes) {
42-
self.attributes = attributes
74+
self.attributes = attributes.filter { key, _ in
75+
for entity in entities {
76+
if entity.attributes.contains(where: { attribute in attribute.key == key }) {
77+
return true
78+
}
79+
if entity.identifiers.contains(where: { attribute in attribute.key == key }) {
80+
return true
81+
}
82+
}
83+
return false
84+
}
4385
} else {
4486
self.attributes = [String: AttributeValue]()
4587
}
88+
4689
}
4790

4891
/// Modifies the current Resource by merging with the other Resource.
4992
/// In case of a collision, new Resource takes precedence.
5093
/// - Parameter other: the Resource that will be merged with this
5194
public mutating func merge(other: Resource) {
5295
attributes.merge(other.attributes) { _, other in other }
96+
entities = Resource.mergeEntities(entities, other.entities)
5397
}
5498

5599
/// Returns a new, merged Resource by merging the current Resource with the other Resource.
56100
/// In case of a collision, new Resource takes precedence.
57101
/// - Parameter other: the Resource that will be merged with this
58102
public func merging(other: Resource) -> Resource {
59103
let labelsCopy = attributes.merging(other.attributes) { _, other in other }
60-
return Resource(attributes: labelsCopy)
104+
let entities = Resource.mergeEntities(self.entities, other.entities)
105+
return Resource(attributes: labelsCopy, entities: entities)
61106
}
62107

63-
private static func checkAttributes(attributes: [String: AttributeValue]) -> Bool {
108+
internal static func checkAttributes(attributes: [String: AttributeValue]) -> Bool {
64109
for entry in attributes where !isValidAndNotEmpty(name: entry.key) {
65110
return false
66111
}

0 commit comments

Comments
 (0)