Skip to content

Commit 67e6762

Browse files
committed
Add the remaining missing pieces to V2 resolved schema.
1 parent 1470468 commit 67e6762

File tree

7 files changed

+307
-23
lines changed

7 files changed

+307
-23
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! Event related definitions structs.
2+
3+
use schemars::JsonSchema;
4+
use serde::{Deserialize, Serialize};
5+
use weaver_semconv::{
6+
attribute::RequirementLevel,
7+
v2::{signal_id::SignalId, CommonFields},
8+
};
9+
10+
use crate::v2::attribute::Attribute;
11+
12+
/// The definition of an event signal.
13+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
14+
#[serde(deny_unknown_fields)]
15+
pub struct Entity {
16+
/// The type of the entity.
17+
pub r#type: SignalId,
18+
19+
/// List of attributes that belong to this event.
20+
#[serde(default)]
21+
#[serde(skip_serializing_if = "Vec::is_empty")]
22+
pub identity: Vec<EntityAttribute>,
23+
24+
/// List of attributes that belong to this event.
25+
#[serde(default)]
26+
#[serde(skip_serializing_if = "Vec::is_empty")]
27+
pub description: Vec<EntityAttribute>,
28+
29+
/// Common fields (like brief, note, annotations).
30+
#[serde(flatten)]
31+
pub common: CommonFields,
32+
}
33+
34+
/// A special type of reference to attributes that remembers event-specicific information.
35+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
36+
#[serde(deny_unknown_fields)]
37+
pub struct EntityAttribute {
38+
/// Base attribute definitions.
39+
#[serde(flatten)]
40+
pub base: Attribute,
41+
/// Specifies if the attribute is mandatory. Can be "required",
42+
/// "conditionally_required", "recommended" or "opt_in". When omitted,
43+
/// the attribute is "recommended". When set to
44+
/// "conditionally_required", the string provided as <condition> MUST
45+
/// specify the conditions under which the attribute is required.
46+
///
47+
/// Note: For attributes that are "recommended" or "opt-in" - not all metric source will
48+
/// create timeseries with these attributes, but for any given timeseries instance, the attributes that *were* present
49+
/// should *remain* present. That is - a metric timeseries cannot drop attributes during its lifetime.
50+
pub requirement_level: RequirementLevel,
51+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//! Event related definitions structs.
2+
3+
use schemars::JsonSchema;
4+
use serde::{Deserialize, Serialize};
5+
use weaver_semconv::{
6+
attribute::RequirementLevel,
7+
v2::{signal_id::SignalId, CommonFields},
8+
};
9+
10+
use crate::v2::attribute::Attribute;
11+
12+
/// The definition of an event signal.
13+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
14+
#[serde(deny_unknown_fields)]
15+
pub struct Event {
16+
/// The name of the event.
17+
pub name: SignalId,
18+
19+
/// List of attributes that belong to this event.
20+
#[serde(default)]
21+
#[serde(skip_serializing_if = "Vec::is_empty")]
22+
pub attributes: Vec<EventAttribute>,
23+
24+
/// Which resources this span should be associated with.
25+
///
26+
/// This list is an "any of" list, where a metric may be associated with one or more entities, but should
27+
/// be associated with at least one in this list.
28+
#[serde(default)]
29+
#[serde(skip_serializing_if = "Vec::is_empty")]
30+
pub entity_associations: Vec<String>,
31+
32+
/// Common fields (like brief, note, annotations).
33+
#[serde(flatten)]
34+
pub common: CommonFields,
35+
}
36+
37+
/// A special type of reference to attributes that remembers event-specicific information.
38+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
39+
#[serde(deny_unknown_fields)]
40+
pub struct EventAttribute {
41+
/// Base attribute definitions.
42+
#[serde(flatten)]
43+
pub base: Attribute,
44+
/// Specifies if the attribute is mandatory. Can be "required",
45+
/// "conditionally_required", "recommended" or "opt_in". When omitted,
46+
/// the attribute is "recommended". When set to
47+
/// "conditionally_required", the string provided as <condition> MUST
48+
/// specify the conditions under which the attribute is required.
49+
///
50+
/// Note: For attributes that are "recommended" or "opt-in" - not all metric source will
51+
/// create timeseries with these attributes, but for any given timeseries instance, the attributes that *were* present
52+
/// should *remain* present. That is - a metric timeseries cannot drop attributes during its lifetime.
53+
pub requirement_level: RequirementLevel,
54+
}
55+
56+
/// A refinement of an event signal, for use in code-gen or specific library application.
57+
///
58+
/// A refinement represents a "view" of an Event that is highly optimised for a particular implementation.
59+
/// e.g. for HTTP events, there may be a refinement that provides only the necessary information for dealing with Java's HTTP
60+
/// client library, and drops optional or extraneous information from the underlying http event.
61+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
62+
pub struct EventRefinement {
63+
/// The identity of the refinement.
64+
pub id: SignalId,
65+
66+
// TODO - This is a lazy way of doing this. We use `type` to refer
67+
// to the underlying span defintiion, but override all fields here.
68+
// We probably should copy-paste all the "span" attributes here
69+
// including the `ty`
70+
/// The definition of the metric refinement.
71+
#[serde(flatten)]
72+
pub event: Event,
73+
}

crates/weaver_forge/src/v2/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Version two of weaver model.
22
33
pub mod attribute;
4+
pub mod entity;
5+
pub mod event;
46
pub mod metric;
57
pub mod registry;
68
pub mod span;

crates/weaver_forge/src/v2/registry.rs

Lines changed: 175 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use crate::{
88
error::Error,
99
v2::{
1010
attribute::Attribute,
11-
metric::{Metric, MetricAttribute, MetricRefinement}, span::{Span, SpanAttribute, SpanRefinement},
11+
entity::{Entity, EntityAttribute},
12+
event::{Event, EventAttribute, EventRefinement},
13+
metric::{Metric, MetricAttribute, MetricRefinement},
14+
span::{Span, SpanAttribute, SpanRefinement},
1215
},
1316
};
1417

@@ -22,7 +25,8 @@ pub struct ResolvedRegistry {
2225
/// The semantic convention registry url.
2326
#[serde(skip_serializing_if = "String::is_empty")]
2427
pub registry_url: String,
25-
// TODO - Attribute registry?
28+
/// The raw attributes in this registry.
29+
pub attributes: Vec<Attribute>,
2630
/// The signals defined in this registry.
2731
pub signals: Signals,
2832
/// The set of refinments defined in this registry.
@@ -37,6 +41,10 @@ pub struct Signals {
3741
pub metrics: Vec<Metric>,
3842
/// The span signals defined.
3943
pub spans: Vec<Span>,
44+
/// The event signals defined.
45+
pub events: Vec<Event>,
46+
/// The entity signals defined.
47+
pub entities: Vec<Entity>,
4048
}
4149

4250
/// The set of all refinements for a semantic convention registry.
@@ -51,6 +59,8 @@ pub struct Refinements {
5159
pub metrics: Vec<MetricRefinement>,
5260
/// The span refinements defined.
5361
pub spans: Vec<SpanRefinement>,
62+
/// The event refinements defined.
63+
pub events: Vec<EventRefinement>,
5464
}
5565

5666
impl ResolvedRegistry {
@@ -59,6 +69,18 @@ impl ResolvedRegistry {
5969
schema: weaver_resolved_schema::v2::ResolvedTelemetrySchema,
6070
) -> Result<Self, Error> {
6171
let mut errors = Vec::new();
72+
let mut attributes: Vec<Attribute> =
73+
schema.catalog.attributes()
74+
.iter()
75+
.map(|a| Attribute {
76+
key: a.key.clone(),
77+
r#type: a.r#type.clone(),
78+
examples: a.examples.clone(),
79+
common: a.common.clone(),
80+
})
81+
.collect();
82+
attributes.sort_by(|l,r| l.key.cmp(&r.key));
83+
6284
let mut metrics = Vec::new();
6385
for metric in schema.registry.metrics {
6486
let attributes = metric
@@ -92,6 +114,7 @@ impl ResolvedRegistry {
92114
common: metric.common,
93115
});
94116
}
117+
metrics.sort_by(|l,r| l.name.cmp(&r.name));
95118

96119
let mut metric_refinements: Vec<MetricRefinement> = Vec::new();
97120
for metric in schema.registry.metric_refinements {
@@ -130,6 +153,7 @@ impl ResolvedRegistry {
130153
},
131154
});
132155
}
156+
metric_refinements.sort_by(|l,r| l.id.cmp(&r.id));
133157

134158
let mut spans = Vec::new();
135159
for span in schema.registry.spans {
@@ -165,6 +189,7 @@ impl ResolvedRegistry {
165189
common: span.common,
166190
});
167191
}
192+
spans.sort_by(|l,r| l.r#type.cmp(&r.r#type));
168193
let mut span_refinements = Vec::new();
169194
for span in schema.registry.span_refinements {
170195
let attributes = span
@@ -191,29 +216,164 @@ impl ResolvedRegistry {
191216
attr
192217
})
193218
.collect();
194-
span_refinements.push(
195-
SpanRefinement {
196-
id: span.id,
197-
span: Span {
198-
r#type: span.span.r#type,
199-
kind: span.span.kind,
200-
name: span.span.name,
201-
attributes,
202-
entity_associations: span.span.entity_associations,
203-
common: span.span.common,
204-
}
205-
});
219+
span_refinements.push(SpanRefinement {
220+
id: span.id,
221+
span: Span {
222+
r#type: span.span.r#type,
223+
kind: span.span.kind,
224+
name: span.span.name,
225+
attributes,
226+
entity_associations: span.span.entity_associations,
227+
common: span.span.common,
228+
},
229+
});
230+
}
231+
span_refinements.sort_by(|l,r| l.id.cmp(&r.id));
232+
233+
let mut events = Vec::new();
234+
for event in schema.registry.events {
235+
let attributes = event
236+
.attributes
237+
.iter()
238+
.filter_map(|ar| {
239+
let attr = schema.catalog.attribute(&ar.base).map(|a| EventAttribute {
240+
base: Attribute {
241+
key: a.key.clone(),
242+
r#type: a.r#type.clone(),
243+
examples: a.examples.clone(),
244+
common: a.common.clone(),
245+
},
246+
requirement_level: ar.requirement_level.clone(),
247+
});
248+
if attr.is_none() {
249+
errors.push(Error::AttributeNotFound {
250+
group_id: format!("event.{}", &event.name),
251+
attr_ref: AttributeRef(ar.base.0),
252+
});
253+
}
254+
attr
255+
})
256+
.collect();
257+
events.push(Event {
258+
name: event.name,
259+
attributes: attributes,
260+
entity_associations: event.entity_associations,
261+
common: event.common,
262+
});
263+
}
264+
events.sort_by(|l,r| l.name.cmp(&r.name));
265+
266+
// convert event refinements.
267+
let mut event_refinements = Vec::new();
268+
for event in schema.registry.event_refinements {
269+
let attributes = event
270+
.event
271+
.attributes
272+
.iter()
273+
.filter_map(|ar| {
274+
let attr = schema.catalog.attribute(&ar.base).map(|a| EventAttribute {
275+
base: Attribute {
276+
key: a.key.clone(),
277+
r#type: a.r#type.clone(),
278+
examples: a.examples.clone(),
279+
common: a.common.clone(),
280+
},
281+
requirement_level: ar.requirement_level.clone(),
282+
});
283+
if attr.is_none() {
284+
errors.push(Error::AttributeNotFound {
285+
group_id: format!("event.{}", &event.id),
286+
attr_ref: AttributeRef(ar.base.0),
287+
});
288+
}
289+
attr
290+
})
291+
.collect();
292+
event_refinements.push(EventRefinement {
293+
id: event.id,
294+
event: Event {
295+
name: event.event.name,
296+
attributes: attributes,
297+
entity_associations: event.event.entity_associations,
298+
common: event.event.common,
299+
},
300+
});
301+
}
302+
event_refinements.sort_by(|l,r| l.id.cmp(&r.id));
303+
304+
let mut entities = Vec::new();
305+
for e in schema.registry.entities {
306+
let identity = e
307+
.identity
308+
.iter()
309+
.filter_map(|ar| {
310+
let attr = schema.catalog.attribute(&ar.base).map(|a| EntityAttribute {
311+
base: Attribute {
312+
key: a.key.clone(),
313+
r#type: a.r#type.clone(),
314+
examples: a.examples.clone(),
315+
common: a.common.clone(),
316+
},
317+
requirement_level: ar.requirement_level.clone(),
318+
});
319+
if attr.is_none() {
320+
errors.push(Error::AttributeNotFound {
321+
group_id: format!("entity.{}", &e.r#type),
322+
attr_ref: AttributeRef(ar.base.0),
323+
});
324+
}
325+
attr
326+
})
327+
.collect();
328+
329+
let description = e
330+
.description
331+
.iter()
332+
.filter_map(|ar| {
333+
let attr = schema.catalog.attribute(&ar.base).map(|a| EntityAttribute {
334+
base: Attribute {
335+
key: a.key.clone(),
336+
r#type: a.r#type.clone(),
337+
examples: a.examples.clone(),
338+
common: a.common.clone(),
339+
},
340+
requirement_level: ar.requirement_level.clone(),
341+
});
342+
if attr.is_none() {
343+
errors.push(Error::AttributeNotFound {
344+
group_id: format!("entity.{}", &e.r#type),
345+
attr_ref: AttributeRef(ar.base.0),
346+
});
347+
}
348+
attr
349+
})
350+
.collect();
351+
entities.push(Entity {
352+
r#type: e.r#type,
353+
identity,
354+
description,
355+
common: e.common,
356+
});
206357
}
358+
entities.sort_by(|l,r| l.r#type.cmp(&r.r#type));
359+
207360
if !errors.is_empty() {
208361
return Err(Error::CompoundError(errors));
209362
}
210363

211364
Ok(Self {
212365
registry_url: schema.schema_url.clone(),
213-
signals: Signals { metrics, spans },
366+
attributes,
367+
signals: Signals {
368+
metrics,
369+
spans,
370+
events,
371+
entities,
372+
},
214373
refinements: Refinements {
215374
metrics: metric_refinements,
216375
spans: span_refinements,
376+
events: event_refinements,
217377
},
218378
})
219379
}

0 commit comments

Comments
 (0)