-
Notifications
You must be signed in to change notification settings - Fork 904
[DO NOT MERGE] Entity Prototype for SDK Specification #7434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 17 commits
f056298
5460d5e
ce0e66d
cb74286
3369be3
2c4aaeb
8af2cd1
da525bd
b119561
ddf096d
9c222dd
2871ff0
34b6f60
0711350
ebf9557
73ef00a
8d4288e
f22ec8d
d220005
f9dcb52
18afb60
7ace665
d5219d1
cba0606
a38a544
d01f5a3
2560c51
bf72978
af3bbd9
2809916
912ba24
634c4a3
5c126c9
7a7c426
8ad0e5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
import io.opentelemetry.api.common.Attributes; | ||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import java.util.function.Consumer; | ||
|
||
/** | ||
* A builder of an Entity that allows to add identifying or descriptive {@link Attributes}, as well | ||
* as type and schema_url. | ||
* | ||
* <p>Entity represents an object of interest associated with produced telemetry: traces, metrics or | ||
* logs. | ||
* | ||
* <p>For example, telemetry produced using OpenTelemetry SDK is normally associated with a Service | ||
* entity. Similarly, OpenTelemetry defines system metrics for a host. The Host is the entity we | ||
* want to associate metrics with in this case. | ||
* | ||
* <p>Entities may be also associated with produced telemetry indirectly. For example a service that | ||
* produces telemetry is also related with a process in which the service runs, so we say that the | ||
* Service entity is related to the Process entity. The process normally also runs on a host, so we | ||
* say that the Process entity is related to the Host entity. | ||
*/ | ||
public interface EntityBuilder { | ||
/** | ||
* Assign an OpenTelemetry schema URL to the resulting Entity. | ||
* | ||
* @param schemaUrl The URL of the OpenTelemetry schema being used to create this Entity. | ||
* @return this | ||
*/ | ||
EntityBuilder setSchemaUrl(String schemaUrl); | ||
|
||
/** | ||
* Modify the descriptive attributes of this Entity. | ||
* | ||
* @param f A {@link Consumer} which builds the descriptive attributes. | ||
* @return this | ||
*/ | ||
EntityBuilder withDescription(Consumer<AttributesBuilder> f); | ||
|
||
/** | ||
* Modify the identifying attributes of this Entity. | ||
* | ||
* @param f A {@link Consumer} which builds the identifying attributes. | ||
* @return this | ||
*/ | ||
EntityBuilder withId(Consumer<AttributesBuilder> f); | ||
|
||
/** Emits the current entity. */ | ||
void emit(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe call this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is anticipation of having an EntityBuilder that just emits Entity without attaching to active resource. I debated two things:
I was planning to talk about this awkwardness in the next Entities SIG, but agree with only "attach" then this should be "attach". |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
import io.opentelemetry.api.OpenTelemetry; | ||
|
||
/** Extension to {@link OpenTelemetry} that adds {@link ResourceProvider}. */ | ||
public interface ExtendedOpenTelemetry extends OpenTelemetry { | ||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** Returns the {@link ResourceProvider} for this {@link OpenTelemetry}. */ | ||
default ResourceProvider getResourceProvider() { | ||
return ResourceProvider.noop(); | ||
Check warning on line 14 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/ExtendedOpenTelemetry.java
|
||
} | ||
|
||
/** Returns the {@link Resource} that telemetry from this {@link OpenTelemetry} uses. */ | ||
default Resource getResource() { | ||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return getResourceProvider().getResource(); | ||
Check warning on line 19 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/ExtendedOpenTelemetry.java
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import java.util.function.Consumer; | ||
|
||
final class NoopEntityBuilder implements EntityBuilder { | ||
Check warning on line 11 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopEntityBuilder.java
|
||
@Override | ||
public EntityBuilder setSchemaUrl(String schemaUrl) { | ||
return this; | ||
Check warning on line 14 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopEntityBuilder.java
|
||
} | ||
|
||
@Override | ||
public EntityBuilder withDescription(Consumer<AttributesBuilder> f) { | ||
return this; | ||
Check warning on line 19 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopEntityBuilder.java
|
||
} | ||
|
||
@Override | ||
public EntityBuilder withId(Consumer<AttributesBuilder> f) { | ||
return this; | ||
Check warning on line 24 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopEntityBuilder.java
|
||
} | ||
|
||
@Override | ||
public void emit() {} | ||
Check warning on line 28 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopEntityBuilder.java
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
final class NoopResource implements Resource { | ||
Check warning on line 8 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopResource.java
|
||
|
||
@Override | ||
public boolean removeEntity(String entityType) { | ||
return false; | ||
Check warning on line 12 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopResource.java
|
||
} | ||
|
||
@Override | ||
public EntityBuilder attachEntity(String entityType) { | ||
return new NoopEntityBuilder(); | ||
Check warning on line 17 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopResource.java
|
||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
final class NoopResourceProvider implements ResourceProvider { | ||
Check warning on line 8 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopResourceProvider.java
|
||
|
||
@Override | ||
public Resource getResource() { | ||
return new NoopResource(); | ||
Check warning on line 12 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/NoopResourceProvider.java
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
/** The active resource for which Telemetry is being generated. */ | ||
public interface Resource { | ||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* Removes an entity from this resource. | ||
* | ||
* @param entityType the type of entity to remove. | ||
* @return true if entity was found and removed. | ||
*/ | ||
public boolean removeEntity(String entityType); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So can multiple instrumentations compete to add or remove an entity with the same type? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. This API is here to explore the browser-SIGs needs where session has changed and needs to be replaced. The current This is the "footgun" we're worried about in Entities SIG and need to explore.
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* Attaches an entity to the current {@link Resource}. | ||
* | ||
* @param entityType The type of the entity. | ||
* @return A builder that can construct an entity. | ||
*/ | ||
public EntityBuilder attachEntity(String entityType); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.api.incubator.entities; | ||
|
||
/** | ||
* A registry for interacting with {@link Resource}s. The name <i>Provider</i> is for consistency | ||
* with other languages and it is <b>NOT</b> loaded using reflection. | ||
* | ||
* @see Resource | ||
*/ | ||
public interface ResourceProvider { | ||
/** | ||
* Returns a no-op {@link ResourceProvider} which only creates no-op {@link Resource}s which do | ||
* not record nor are emitted. | ||
*/ | ||
static ResourceProvider noop() { | ||
return new NoopResourceProvider(); | ||
Check warning on line 20 in api/incubator/src/main/java/io/opentelemetry/api/incubator/entities/ResourceProvider.java
|
||
} | ||
|
||
/** Returns the active {@link Resource} for which Telemetry is reported. */ | ||
Resource getResource(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
Comparing source compatibility of opentelemetry-sdk-common-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-common-1.51.0.jar | ||
No changes. | ||
*** MODIFIED CLASS: PUBLIC ABSTRACT io.opentelemetry.sdk.resources.Resource (not serializable) | ||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0 | ||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.resources.Resource create(io.opentelemetry.api.common.Attributes, java.lang.String, java.util.Collection<io.opentelemetry.sdk.resources.internal.Entity>) | ||
*** MODIFIED METHOD: PUBLIC NON_ABSTRACT (<- ABSTRACT) io.opentelemetry.api.common.Attributes getAttributes() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
Comparing source compatibility of opentelemetry-sdk-testing-1.52.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.51.0.jar | ||
No changes. | ||
+++ NEW CLASS: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EntityAssert (not serializable) | ||
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. | ||
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EntityAssert hasDescriptionSatisfying(org.assertj.core.api.ThrowingConsumer<io.opentelemetry.api.common.Attributes>) | ||
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EntityAssert hasIdSatisfying(org.assertj.core.api.ThrowingConsumer<io.opentelemetry.api.common.Attributes>) | ||
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EntityAssert hasSchemaUrl(java.lang.String) | ||
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EntityAssert hasType(java.lang.String) | ||
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions (not serializable) | ||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0 | ||
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.testing.assertj.EntityAssert assertThat(io.opentelemetry.sdk.resources.internal.Entity) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.exporter.internal.otlp; | ||
|
||
import io.opentelemetry.api.internal.StringUtils; | ||
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil; | ||
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize; | ||
import io.opentelemetry.exporter.internal.marshal.Serializer; | ||
import io.opentelemetry.proto.common.v1.internal.EntityRef; | ||
import io.opentelemetry.sdk.resources.internal.Entity; | ||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* A Marshaler of {@link io.opentelemetry.sdk.resources.Entity}. | ||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change | ||
* at any time. | ||
*/ | ||
public final class EntityRefMarshaler extends MarshalerWithSize { | ||
jsuereth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@Nullable private final byte[] schemaUrlUtf8; | ||
private final byte[] typeUtf8; | ||
private final byte[][] idKeysUtf8; | ||
private final byte[][] descriptionKeysUtf8; | ||
|
||
@Override | ||
protected void writeTo(Serializer output) throws IOException { | ||
if (schemaUrlUtf8 != null) { | ||
output.writeString(EntityRef.SCHEMA_URL, schemaUrlUtf8); | ||
} | ||
output.writeString(EntityRef.TYPE, typeUtf8); | ||
output.writeRepeatedString(EntityRef.ID_KEYS, idKeysUtf8); | ||
output.writeRepeatedString(EntityRef.DESCRIPTION_KEYS, descriptionKeysUtf8); | ||
} | ||
|
||
/** Consttructs an entity reference marshaler from a full entity. */ | ||
public static EntityRefMarshaler createForEntity(Entity e) { | ||
byte[] schemaUrlUtf8 = null; | ||
if (!StringUtils.isNullOrEmpty(e.getSchemaUrl())) { | ||
schemaUrlUtf8 = e.getSchemaUrl().getBytes(StandardCharsets.UTF_8); | ||
} | ||
return new EntityRefMarshaler( | ||
schemaUrlUtf8, | ||
e.getType().getBytes(StandardCharsets.UTF_8), | ||
e.getId().asMap().keySet().stream() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eventually we'll want to make this more efficient, avoiding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. This reminds me of the "dictonary" / "register an attribute set" API discussion from the spec meeting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, if it wasn't apparent for now - This marshaller is only used ONCE per resource instance. So unless resource is being updated frequently (which we do not expect), then this cost is not paid often, if more than once. |
||
.map(key -> key.getKey().getBytes(StandardCharsets.UTF_8)) | ||
.toArray(byte[][]::new), | ||
e.getDescription().asMap().keySet().stream() | ||
.map(key -> key.getKey().getBytes(StandardCharsets.UTF_8)) | ||
.toArray(byte[][]::new)); | ||
} | ||
|
||
private EntityRefMarshaler( | ||
@Nullable byte[] schemaUrlUtf8, | ||
byte[] typeUtf8, | ||
byte[][] idKeysUtf8, | ||
byte[][] descriptionKeysUtf8) { | ||
super(calculateSize(schemaUrlUtf8, typeUtf8, idKeysUtf8, descriptionKeysUtf8)); | ||
this.schemaUrlUtf8 = schemaUrlUtf8; | ||
this.typeUtf8 = typeUtf8; | ||
this.idKeysUtf8 = idKeysUtf8; | ||
this.descriptionKeysUtf8 = descriptionKeysUtf8; | ||
} | ||
|
||
private static int calculateSize( | ||
@Nullable byte[] schemaUrlUtf8, | ||
byte[] typeUtf8, | ||
byte[][] idKeysUtf8, | ||
byte[][] descriptionKeysUtf8) { | ||
int size = 0; | ||
if (schemaUrlUtf8 != null) { | ||
size += MarshalerUtil.sizeBytes(EntityRef.SCHEMA_URL, schemaUrlUtf8); | ||
} | ||
size += MarshalerUtil.sizeBytes(EntityRef.TYPE, typeUtf8); | ||
MarshalerUtil.sizeRepeatedString(EntityRef.ID_KEYS, idKeysUtf8); | ||
MarshalerUtil.sizeRepeatedString(EntityRef.DESCRIPTION_KEYS, descriptionKeysUtf8); | ||
return size; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.