| /* |
| * Copyright 2018, OpenCensus Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package io.opencensus.common; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.ByteOrder; |
| |
| /** |
| * A service class to encode/decode {@link ServerStats} as defined by the spec. |
| * |
| * <p>See <a |
| * href="https://github.com/census-instrumentation/opencensus-specs/blob/master/encodings/CensusServerStatsEncoding.md">opencensus-server-stats-specs</a> |
| * for encoding {@code ServerStats} |
| * |
| * <p>Use {@code ServerStatsEncoding.toBytes(ServerStats stats)} to encode. |
| * |
| * <p>Use {@code ServerStatsEncoding.parseBytes(byte[] serialized)} to decode. |
| * |
| * @since 0.16 |
| */ |
| public final class ServerStatsEncoding { |
| |
| private ServerStatsEncoding() {} |
| |
| /** |
| * The current encoding version. The value is {@value #CURRENT_VERSION} |
| * |
| * @since 0.16 |
| */ |
| public static final byte CURRENT_VERSION = (byte) 0; |
| |
| /** |
| * Encodes the {@link ServerStats} as per the Opencensus Summary Span specification. |
| * |
| * @param stats {@code ServerStats} to encode. |
| * @return encoded byte array. |
| * @since 0.16 |
| */ |
| public static byte[] toBytes(ServerStats stats) { |
| // Should this be optimized to not include invalid values? |
| |
| ByteBuffer bb = ByteBuffer.allocate(ServerStatsFieldEnums.getTotalSize() + 1); |
| bb.order(ByteOrder.LITTLE_ENDIAN); |
| |
| // put version |
| bb.put(CURRENT_VERSION); |
| |
| bb.put((byte) ServerStatsFieldEnums.Id.SERVER_STATS_LB_LATENCY_ID.value()); |
| bb.putLong(stats.getLbLatencyNs()); |
| |
| bb.put((byte) ServerStatsFieldEnums.Id.SERVER_STATS_SERVICE_LATENCY_ID.value()); |
| bb.putLong(stats.getServiceLatencyNs()); |
| |
| bb.put((byte) ServerStatsFieldEnums.Id.SERVER_STATS_TRACE_OPTION_ID.value()); |
| bb.put(stats.getTraceOption()); |
| return bb.array(); |
| } |
| |
| /** |
| * Decodes serialized byte array to create {@link ServerStats} as per Opencensus Summary Span |
| * specification. |
| * |
| * @param serialized encoded {@code ServerStats} in byte array. |
| * @return decoded {@code ServerStats}. null if decoding fails. |
| * @since 0.16 |
| */ |
| public static ServerStats parseBytes(byte[] serialized) |
| throws ServerStatsDeserializationException { |
| final ByteBuffer bb = ByteBuffer.wrap(serialized); |
| bb.order(ByteOrder.LITTLE_ENDIAN); |
| long serviceLatencyNs = 0L; |
| long lbLatencyNs = 0L; |
| byte traceOption = (byte) 0; |
| |
| // Check the version first. |
| if (!bb.hasRemaining()) { |
| throw new ServerStatsDeserializationException("Serialized ServerStats buffer is empty"); |
| } |
| byte version = bb.get(); |
| |
| if (version > CURRENT_VERSION || version < 0) { |
| throw new ServerStatsDeserializationException("Invalid ServerStats version: " + version); |
| } |
| |
| while (bb.hasRemaining()) { |
| ServerStatsFieldEnums.Id id = ServerStatsFieldEnums.Id.valueOf((int) bb.get() & 0xFF); |
| if (id == null) { |
| // Skip remaining; |
| bb.position(bb.limit()); |
| } else { |
| switch (id) { |
| case SERVER_STATS_LB_LATENCY_ID: |
| lbLatencyNs = bb.getLong(); |
| break; |
| case SERVER_STATS_SERVICE_LATENCY_ID: |
| serviceLatencyNs = bb.getLong(); |
| break; |
| case SERVER_STATS_TRACE_OPTION_ID: |
| traceOption = bb.get(); |
| break; |
| } |
| } |
| } |
| try { |
| return ServerStats.create(lbLatencyNs, serviceLatencyNs, traceOption); |
| } catch (IllegalArgumentException e) { |
| throw new ServerStatsDeserializationException( |
| "Serialized ServiceStats contains invalid values: " + e.getMessage()); |
| } |
| } |
| } |