Skip to content

Commit 5f27364

Browse files
committed
feat(x-goog-spanner-request-id): commit foundation
This change adds in the bases to bring in the functionality for the "x-goog-spanner-request-id" that'll be used for debugging without the limits of trace continuity and sampling. Updates googleapis#3537
1 parent c74369b commit 5f27364

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2025 Google LLC
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 com.google.cloud.spanner;
18+
19+
import java.security.SecureRandom;
20+
21+
public class XGoogSpannerRequestId {
22+
// 1. Generate the random process Id singleton.
23+
public static String RAND_PROCESS_ID = XGoogSpannerRequestId.generateRandProcessId();
24+
public static long VERSION = 1; // The version of the specification being implemented.
25+
private long nthClientId;
26+
private long nthChannelId;
27+
private long nthRequest;
28+
private long attempt;
29+
30+
public XGoogSpannerRequestId(long nthClientId, long nthChannelId, long nthRequest, long attempt) {
31+
this.nthClientId = nthClientId;
32+
this.nthChannelId = nthChannelId;
33+
this.nthRequest = nthRequest;
34+
this.attempt = attempt;
35+
}
36+
37+
public static XGoogSpannerRequestId of(
38+
long nthClientId, long nthChannelId, long nthRequest, long attempt) {
39+
return new XGoogSpannerRequestId(nthClientId, nthChannelId, nthRequest, attempt);
40+
}
41+
42+
private static String generateRandProcessId() {
43+
byte[] rBytes = new byte[8];
44+
SecureRandom srng = new SecureRandom();
45+
srng.nextBytes(rBytes);
46+
int result =
47+
Byte.toUnsignedInt(rBytes[0])
48+
| Byte.toUnsignedInt(rBytes[1]) << 8
49+
| Byte.toUnsignedInt(rBytes[2]) << 16
50+
| Byte.toUnsignedInt(rBytes[3]) << 24;
51+
52+
return Integer.toHexString(result);
53+
}
54+
55+
public String toString() {
56+
return String.format(
57+
"%d.%s.%d.%d.%d.%d",
58+
this.VERSION,
59+
this.RAND_PROCESS_ID,
60+
this.nthClientId,
61+
this.nthChannelId,
62+
this.nthRequest,
63+
this.attempt);
64+
}
65+
66+
@Override
67+
public boolean equals(Object other) {
68+
if (other == null) {
69+
return false;
70+
}
71+
72+
if (!(other instanceof XGoogSpannerRequestId)) {
73+
return false;
74+
}
75+
76+
XGoogSpannerRequestId otherReqId = (XGoogSpannerRequestId) (other);
77+
return otherReqId.toString().equals(this.toString());
78+
}
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2025 Google LLC
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+
* https://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 com.google.cloud.spanner;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import java.util.regex.Matcher;
22+
import java.util.regex.Pattern;
23+
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
import org.junit.runners.JUnit4;
26+
27+
@RunWith(JUnit4.class)
28+
public class XGoogSpannerRequestIdTest {
29+
private static String RAND_PROCESS_ID = XGoogSpannerRequestId.RAND_PROCESS_ID;
30+
private static Pattern REGEX_RAND_PROCESS_ID =
31+
Pattern.compile("1.([0-9a-z]{8})(\\.\\d+){3}\\.(\\d+)$");
32+
33+
@Test
34+
public void testEquals() {
35+
XGoogSpannerRequestId reqID1 = XGoogSpannerRequestId.of(1, 1, 1, 1);
36+
XGoogSpannerRequestId reqID2 = XGoogSpannerRequestId.of(1, 1, 1, 1);
37+
assertThat(reqID1).isEqualTo(reqID2);
38+
assertThat(reqID1).isEqualTo(reqID1);
39+
assertThat(reqID2).isEqualTo(reqID2);
40+
41+
XGoogSpannerRequestId reqID3 = XGoogSpannerRequestId.of(1, 1, 1, 2);
42+
assertThat(reqID1).isNotEqualTo(reqID3);
43+
assertThat(reqID3).isNotEqualTo(reqID1);
44+
assertThat(reqID3).isEqualTo(reqID3);
45+
}
46+
47+
@Test
48+
public void testEnsureHexadecimalFormatForRandProcessID() {
49+
String str = XGoogSpannerRequestId.of(1, 2, 3, 4).toString();
50+
Matcher m = REGEX_RAND_PROCESS_ID.matcher(str);
51+
assertThat(m.matches()).isEqualTo(true);
52+
}
53+
}

0 commit comments

Comments
 (0)