Skip to content

Commit

Permalink
Add Marshalers for profiling signal type (#6680)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhalliday authored Sep 20, 2024
1 parent 7990392 commit af59cc4
Show file tree
Hide file tree
Showing 5 changed files with 439 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.otlp.profiles;

import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.internal.otlp.InstrumentationScopeMarshaler;
import io.opentelemetry.proto.profiles.v1experimental.internal.ScopeProfiles;
import java.io.IOException;
import java.util.List;

final class InstrumentationScopeProfilesMarshaler extends MarshalerWithSize {

private final InstrumentationScopeMarshaler instrumentationScope;
private final List<ProfileContainerMarshaler> profileContainerMarshalers;
private final byte[] schemaUrlUtf8;

InstrumentationScopeProfilesMarshaler(
InstrumentationScopeMarshaler instrumentationScope,
byte[] schemaUrlUtf8,
List<ProfileContainerMarshaler> profileContainerMarshalers) {
super(calculateSize(instrumentationScope, schemaUrlUtf8, profileContainerMarshalers));
this.instrumentationScope = instrumentationScope;
this.schemaUrlUtf8 = schemaUrlUtf8;
this.profileContainerMarshalers = profileContainerMarshalers;
}

@Override
public void writeTo(Serializer output) throws IOException {
output.serializeMessage(ScopeProfiles.SCOPE, instrumentationScope);
output.serializeRepeatedMessage(ScopeProfiles.PROFILES, profileContainerMarshalers);
output.serializeString(ScopeProfiles.SCHEMA_URL, schemaUrlUtf8);
}

private static int calculateSize(
InstrumentationScopeMarshaler instrumentationScope,
byte[] schemaUrlUtf8,
List<ProfileContainerMarshaler> profileContainerMarshalers) {
int size = 0;
size += MarshalerUtil.sizeMessage(ScopeProfiles.SCOPE, instrumentationScope);
size += MarshalerUtil.sizeRepeatedMessage(ScopeProfiles.PROFILES, profileContainerMarshalers);
size += MarshalerUtil.sizeBytes(ScopeProfiles.SCHEMA_URL, schemaUrlUtf8);
return size;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.otlp.profiles;

import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.internal.otlp.KeyValueMarshaler;
import io.opentelemetry.proto.profiles.v1experimental.internal.ProfileContainer;
import java.io.IOException;

final class ProfileContainerMarshaler extends MarshalerWithSize {

private final byte[] profileId;
private final long startEpochNanos;
private final long endEpochNanos;
private final KeyValueMarshaler[] attributeMarshalers;
private final int droppedAttributesCount;
private final byte[] originalPayloadFormatUtf8;
private final byte[] originalPayload;
private final ProfileMarshaler profileMarshaler;

static ProfileContainerMarshaler create(ProfileContainerData profileContainerData) {
int droppedAttributesCount =
profileContainerData.getTotalAttributeCount() - profileContainerData.getAttributes().size();

// Not ideal, but this will do for now. ByteBuffer support in
// Serialzer/CodedOutputStream/MarshalerUtilwill follow in a separate step.
byte[] originalPayload = new byte[profileContainerData.getOriginalPayload().remaining()];
profileContainerData.getOriginalPayload().get(originalPayload);

return new ProfileContainerMarshaler(
profileContainerData.getProfileIdBytes(),
profileContainerData.getStartEpochNanos(),
profileContainerData.getEndEpochNanos(),
KeyValueMarshaler.createForAttributes(profileContainerData.getAttributes()),
droppedAttributesCount,
MarshalerUtil.toBytes(profileContainerData.getOriginalPayloadFormat()),
originalPayload,
ProfileMarshaler.create(profileContainerData.getProfile()));
}

private ProfileContainerMarshaler(
byte[] profileId,
long startEpochNanos,
long endEpochNanos,
KeyValueMarshaler[] attributeMarshalers,
int droppedAttributesCount,
byte[] originalPayloadFormat,
byte[] originalPayload,
ProfileMarshaler profileMarshaler) {
super(
calculateSize(
profileId,
startEpochNanos,
endEpochNanos,
attributeMarshalers,
droppedAttributesCount,
originalPayloadFormat,
originalPayload,
profileMarshaler));
this.profileId = profileId;
this.startEpochNanos = startEpochNanos;
this.endEpochNanos = endEpochNanos;
this.attributeMarshalers = attributeMarshalers;
this.droppedAttributesCount = droppedAttributesCount;
this.originalPayloadFormatUtf8 = originalPayloadFormat;
this.originalPayload = originalPayload;
this.profileMarshaler = profileMarshaler;
}

@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeBytes(ProfileContainer.PROFILE_ID, profileId);
output.serializeFixed64(ProfileContainer.START_TIME_UNIX_NANO, startEpochNanos);
output.serializeFixed64(ProfileContainer.END_TIME_UNIX_NANO, endEpochNanos);
output.serializeRepeatedMessage(ProfileContainer.ATTRIBUTES, attributeMarshalers);
output.serializeUInt32(ProfileContainer.DROPPED_ATTRIBUTES_COUNT, droppedAttributesCount);
output.serializeString(ProfileContainer.ORIGINAL_PAYLOAD_FORMAT, originalPayloadFormatUtf8);
output.serializeBytes(ProfileContainer.ORIGINAL_PAYLOAD, originalPayload);
output.serializeMessage(ProfileContainer.PROFILE, profileMarshaler);
}

private static int calculateSize(
byte[] profileId,
long startEpochNanos,
long endEpochNanos,
KeyValueMarshaler[] attributeMarshalers,
int droppedAttributesCount,
byte[] originalPayloadFormat,
byte[] originalPayload,
ProfileMarshaler profileMarshaler) {
int size;
size = 0;
size += MarshalerUtil.sizeBytes(ProfileContainer.PROFILE_ID, profileId);
size += MarshalerUtil.sizeFixed64(ProfileContainer.START_TIME_UNIX_NANO, startEpochNanos);
size += MarshalerUtil.sizeFixed64(ProfileContainer.END_TIME_UNIX_NANO, endEpochNanos);
size += MarshalerUtil.sizeRepeatedMessage(ProfileContainer.ATTRIBUTES, attributeMarshalers);
size +=
MarshalerUtil.sizeUInt32(ProfileContainer.DROPPED_ATTRIBUTES_COUNT, droppedAttributesCount);
size +=
MarshalerUtil.sizeBytes(ProfileContainer.ORIGINAL_PAYLOAD_FORMAT, originalPayloadFormat);
size += MarshalerUtil.sizeBytes(ProfileContainer.ORIGINAL_PAYLOAD, originalPayload);
size += MarshalerUtil.sizeMessage(ProfileContainer.PROFILE, profileMarshaler);
return size;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.otlp.profiles;

import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.ProtoFieldInfo;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.proto.collector.profiles.v1experimental.internal.ExportProfilesServiceRequest;
import java.io.IOException;
import java.util.Collection;

/**
* {@link Marshaler} to convert SDK {@link ProfileContainerData} to OTLP
* ExportProfilesServiceRequest.
*
* <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 ProfilesRequestMarshaler extends MarshalerWithSize {

private static final ProtoFieldInfo RESOURCE_PROFILES =
ExportProfilesServiceRequest.RESOURCE_PROFILES;

private final ResourceProfilesMarshaler[] resourceProfilesMarshalers;

/**
* Returns a {@link ProfilesRequestMarshaler} that can be used to convert the provided {@link
* ProfileContainerData} into a serialized OTLP ExportProfilesServiceRequest.
*/
public static ProfilesRequestMarshaler create(
Collection<ProfileContainerData> profileContainerList) {
return new ProfilesRequestMarshaler(ResourceProfilesMarshaler.create(profileContainerList));
}

private ProfilesRequestMarshaler(ResourceProfilesMarshaler[] resourceProfilesMarshalers) {
super(MarshalerUtil.sizeRepeatedMessage(RESOURCE_PROFILES, resourceProfilesMarshalers));
this.resourceProfilesMarshalers = resourceProfilesMarshalers;
}

@Override
public void writeTo(Serializer output) throws IOException {
output.serializeRepeatedMessage(RESOURCE_PROFILES, resourceProfilesMarshalers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.otlp.profiles;

import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.internal.otlp.InstrumentationScopeMarshaler;
import io.opentelemetry.exporter.internal.otlp.ResourceMarshaler;
import io.opentelemetry.proto.profiles.v1experimental.internal.ResourceProfiles;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.resources.Resource;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

final class ResourceProfilesMarshaler extends MarshalerWithSize {

private final ResourceMarshaler resourceMarshaler;
private final byte[] schemaUrl;
private final InstrumentationScopeProfilesMarshaler[] instrumentationScopeProfilesMarshalers;

/** Returns Marshalers of ResourceProfiles created by grouping the provided Profiles. */
@SuppressWarnings("AvoidObjectArrays")
static ResourceProfilesMarshaler[] create(Collection<ProfileContainerData> profiles) {
Map<Resource, Map<InstrumentationScopeInfo, List<ProfileContainerMarshaler>>>
resourceAndScopeMap = groupByResourceAndScope(profiles);

ResourceProfilesMarshaler[] resourceProfilesMarshalers =
new ResourceProfilesMarshaler[resourceAndScopeMap.size()];
int posResource = 0;
for (Map.Entry<Resource, Map<InstrumentationScopeInfo, List<ProfileContainerMarshaler>>> entry :
resourceAndScopeMap.entrySet()) {
InstrumentationScopeProfilesMarshaler[] instrumentationLibrarySpansMarshalers =
new InstrumentationScopeProfilesMarshaler[entry.getValue().size()];
int posInstrumentation = 0;

for (Map.Entry<InstrumentationScopeInfo, List<ProfileContainerMarshaler>> entryIs :
entry.getValue().entrySet()) {
instrumentationLibrarySpansMarshalers[posInstrumentation++] =
new InstrumentationScopeProfilesMarshaler(
InstrumentationScopeMarshaler.create(entryIs.getKey()),
MarshalerUtil.toBytes(entryIs.getKey().getSchemaUrl()),
entryIs.getValue());
}

resourceProfilesMarshalers[posResource++] =
new ResourceProfilesMarshaler(
ResourceMarshaler.create(entry.getKey()),
MarshalerUtil.toBytes(entry.getKey().getSchemaUrl()),
instrumentationLibrarySpansMarshalers);
}

return resourceProfilesMarshalers;
}

private ResourceProfilesMarshaler(
ResourceMarshaler resourceMarshaler,
byte[] schemaUrl,
InstrumentationScopeProfilesMarshaler[] instrumentationScopeProfilesMarshalers) {
super(calculateSize(resourceMarshaler, schemaUrl, instrumentationScopeProfilesMarshalers));
this.resourceMarshaler = resourceMarshaler;
this.schemaUrl = schemaUrl;
this.instrumentationScopeProfilesMarshalers = instrumentationScopeProfilesMarshalers;
}

@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeMessage(ResourceProfiles.RESOURCE, resourceMarshaler);
output.serializeRepeatedMessage(
ResourceProfiles.SCOPE_PROFILES, instrumentationScopeProfilesMarshalers);
output.serializeString(ResourceProfiles.SCHEMA_URL, schemaUrl);
}

private static int calculateSize(
ResourceMarshaler resourceMarshaler,
byte[] schemaUrl,
InstrumentationScopeProfilesMarshaler[] instrumentationScopeProfilesMarshalers) {
int size = 0;
size += MarshalerUtil.sizeMessage(ResourceProfiles.RESOURCE, resourceMarshaler);
size +=
MarshalerUtil.sizeRepeatedMessage(
ResourceProfiles.SCOPE_PROFILES, instrumentationScopeProfilesMarshalers);
size += MarshalerUtil.sizeBytes(ResourceProfiles.SCHEMA_URL, schemaUrl);
return size;
}

private static Map<Resource, Map<InstrumentationScopeInfo, List<ProfileContainerMarshaler>>>
groupByResourceAndScope(Collection<ProfileContainerData> profiles) {
return MarshalerUtil.groupByResourceAndScope(
profiles,
ProfileContainerData::getResource,
ProfileContainerData::getInstrumentationScopeInfo,
ProfileContainerMarshaler::create);
}
}
Loading

0 comments on commit af59cc4

Please sign in to comment.