1 /* 2 * Copyright 2017, OpenCensus Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.opencensus.trace.propagation; 18 19 import io.opencensus.internal.Utils; 20 import io.opencensus.trace.SpanContext; 21 import java.text.ParseException; 22 23 /** 24 * This is a helper class for {@link SpanContext} propagation on the wire using binary encoding. 25 * 26 * <p>Example of usage on the client: 27 * 28 * <pre>{@code 29 * private static final Tracer tracer = Tracing.getTracer(); 30 * private static final BinaryFormat binaryFormat = 31 * Tracing.getPropagationComponent().getBinaryFormat(); 32 * void onSendRequest() { 33 * try (Scope ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) { 34 * byte[] binaryValue = binaryFormat.toByteArray(tracer.getCurrentContext().context()); 35 * // Send the request including the binaryValue and wait for the response. 36 * } 37 * } 38 * }</pre> 39 * 40 * <p>Example of usage on the server: 41 * 42 * <pre>{@code 43 * private static final Tracer tracer = Tracing.getTracer(); 44 * private static final BinaryFormat binaryFormat = 45 * Tracing.getPropagationComponent().getBinaryFormat(); 46 * void onRequestReceived() { 47 * // Get the binaryValue from the request. 48 * SpanContext spanContext = SpanContext.INVALID; 49 * try { 50 * if (binaryValue != null) { 51 * spanContext = binaryFormat.fromByteArray(binaryValue); 52 * } 53 * } catch (SpanContextParseException e) { 54 * // Maybe log the exception. 55 * } 56 * try (Scope ss = 57 * tracer.spanBuilderWithRemoteParent("Recv.MyRequest", spanContext).startScopedSpan()) { 58 * // Handle request and send response back. 59 * } 60 * } 61 * }</pre> 62 * 63 * @since 0.5 64 */ 65 public abstract class BinaryFormat { 66 static final NoopBinaryFormat NOOP_BINARY_FORMAT = new NoopBinaryFormat(); 67 68 /** 69 * Serializes a {@link SpanContext} into a byte array using the binary format. 70 * 71 * @deprecated use {@link #toByteArray(SpanContext)}. 72 * @param spanContext the {@code SpanContext} to serialize. 73 * @return the serialized binary value. 74 * @throws NullPointerException if the {@code spanContext} is {@code null}. 75 * @since 0.5 76 */ 77 @Deprecated toBinaryValue(SpanContext spanContext)78 public byte[] toBinaryValue(SpanContext spanContext) { 79 return toByteArray(spanContext); 80 } 81 82 /** 83 * Serializes a {@link SpanContext} into a byte array using the binary format. 84 * 85 * @param spanContext the {@code SpanContext} to serialize. 86 * @return the serialized binary value. 87 * @throws NullPointerException if the {@code spanContext} is {@code null}. 88 * @since 0.7 89 */ toByteArray(SpanContext spanContext)90 public byte[] toByteArray(SpanContext spanContext) { 91 // Implementation must override this method. 92 return toBinaryValue(spanContext); 93 } 94 95 /** 96 * Parses the {@link SpanContext} from a byte array using the binary format. 97 * 98 * @deprecated use {@link #fromByteArray(byte[])}. 99 * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. 100 * @return the parsed {@code SpanContext}. 101 * @throws NullPointerException if the {@code input} is {@code null}. 102 * @throws ParseException if the version is not supported or the input is invalid 103 * @since 0.5 104 */ 105 @Deprecated fromBinaryValue(byte[] bytes)106 public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { 107 try { 108 return fromByteArray(bytes); 109 } catch (SpanContextParseException e) { 110 throw new ParseException(e.toString(), 0); 111 } 112 } 113 114 /** 115 * Parses the {@link SpanContext} from a byte array using the binary format. 116 * 117 * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. 118 * @return the parsed {@code SpanContext}. 119 * @throws NullPointerException if the {@code input} is {@code null}. 120 * @throws SpanContextParseException if the version is not supported or the input is invalid 121 * @since 0.7 122 */ fromByteArray(byte[] bytes)123 public SpanContext fromByteArray(byte[] bytes) throws SpanContextParseException { 124 // Implementation must override this method. If it doesn't, the below will StackOverflowError. 125 try { 126 return fromBinaryValue(bytes); 127 } catch (ParseException e) { 128 throw new SpanContextParseException("Error while parsing.", e); 129 } 130 } 131 132 /** 133 * Returns the no-op implementation of the {@code BinaryFormat}. 134 * 135 * @return the no-op implementation of the {@code BinaryFormat}. 136 */ getNoopBinaryFormat()137 static BinaryFormat getNoopBinaryFormat() { 138 return NOOP_BINARY_FORMAT; 139 } 140 141 private static final class NoopBinaryFormat extends BinaryFormat { 142 @Override toByteArray(SpanContext spanContext)143 public byte[] toByteArray(SpanContext spanContext) { 144 Utils.checkNotNull(spanContext, "spanContext"); 145 return new byte[0]; 146 } 147 148 @Override fromByteArray(byte[] bytes)149 public SpanContext fromByteArray(byte[] bytes) { 150 Utils.checkNotNull(bytes, "bytes"); 151 return SpanContext.INVALID; 152 } 153 NoopBinaryFormat()154 private NoopBinaryFormat() {} 155 } 156 } 157