Skip to content

Commit 8ec5aef

Browse files
sfc-gh-ggengclaude
andcommitted
[SNOW-3249917] JDBC removal Step 9b: Replicate OOB telemetry classes
Verbatim replication of JDBC OOB telemetry infrastructure: - TelemetryEvent (182 lines) — telemetry event builder with MetricBuilder/LogBuilder. Source: net.snowflake.client.jdbc.telemetryOOB.TelemetryEvent - TelemetryService (651 lines) — OOB telemetry singleton with deployment configuration and async upload. Source: net.snowflake.client.jdbc.telemetryOOB.TelemetryService - version.properties — resource bundle for driver version string (used by TelemetryEvent.Builder) - SnowflakeDriverConstants — constants from LoginInfoDTO.SF_JDBC_APP_ID and SnowflakeDriver.implementVersion SFException kept from JDBC temporarily (used as parameter type in TelemetryEvent.LogBuilder.withException). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7928ad9 commit 8ec5aef

File tree

3 files changed

+852
-0
lines changed

3 files changed

+852
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/*
2+
* Replicated from snowflake-jdbc (v3.25.1)
3+
* Source: https://github.com/snowflakedb/snowflake-jdbc/blob/v3.25.1/src/main/java/net/snowflake/client/jdbc/telemetryOOB/TelemetryEvent.java
4+
*
5+
* Permitted differences: package, UUIDUtils/SecretDetector use ingest versions
6+
* (fileTransferAgent.log package), SFTimestamp/ResourceBundleManager/TelemetryService
7+
* use ingest versions (same package).
8+
* SFException kept from JDBC temporarily (used as parameter type).
9+
* ResourceBundleManager path updated to ingest package.
10+
*/
11+
package net.snowflake.ingest.streaming.internal.fileTransferAgent;
12+
13+
import java.io.PrintWriter;
14+
import java.io.StringWriter;
15+
import java.util.HashMap;
16+
import net.minidev.json.JSONArray;
17+
import net.minidev.json.JSONObject;
18+
import net.snowflake.client.core.SFException;
19+
import net.snowflake.ingest.streaming.internal.fileTransferAgent.log.SecretDetector;
20+
import net.snowflake.ingest.streaming.internal.fileTransferAgent.log.UUIDUtils;
21+
22+
/** Telemetry Event Class */
23+
public class TelemetryEvent extends JSONObject {
24+
private static final long serialVersionUID = 1L;
25+
private static final int schemaVersion = 1;
26+
27+
public enum Type {
28+
Metric,
29+
Log
30+
}
31+
32+
/** Build metric json object */
33+
public static class MetricBuilder extends Builder<MetricBuilder> {
34+
35+
public MetricBuilder withException(Exception ex) {
36+
this.withName("Exception:" + ex.getMessage());
37+
this.withValue(1);
38+
return this;
39+
}
40+
41+
public MetricBuilder() {
42+
super(MetricBuilder.class);
43+
}
44+
45+
public MetricBuilder withValue(int value) {
46+
body.put("Value", value);
47+
return this;
48+
}
49+
50+
public MetricBuilder withValue(float value) {
51+
body.put("Value", value);
52+
return this;
53+
}
54+
55+
public TelemetryEvent build() {
56+
TelemetryEvent event = super.build();
57+
event.put("Type", Type.Metric);
58+
return event;
59+
}
60+
}
61+
62+
/** Build log json object */
63+
public static class LogBuilder extends Builder<LogBuilder> {
64+
public LogBuilder() {
65+
super(LogBuilder.class);
66+
}
67+
68+
/**
69+
* build a log event for an exception including the full stack trace
70+
*
71+
* @param ex The exception to build a log event
72+
* @return The log event builder
73+
*/
74+
public LogBuilder withException(Exception ex) {
75+
this.withName("Exception:" + ex.getMessage());
76+
StringWriter sw = new StringWriter();
77+
PrintWriter pw = new PrintWriter(sw);
78+
ex.printStackTrace(pw);
79+
String stackTrace = sw.toString(); // stack trace as a string
80+
this.withValue(stackTrace);
81+
return this;
82+
}
83+
84+
public LogBuilder withException(final SFException ex) {
85+
this.withName("Exception:" + ex.getMessage());
86+
StringWriter sw = new StringWriter();
87+
PrintWriter pw = new PrintWriter(sw);
88+
ex.printStackTrace(pw);
89+
String stackTrace = sw.toString(); // stack trace as a string
90+
this.withValue(stackTrace);
91+
return this;
92+
}
93+
94+
public LogBuilder withValue(String value) {
95+
body.put("Value", SecretDetector.maskSecrets(value));
96+
return this;
97+
}
98+
99+
public LogBuilder withValue(JSONObject value) {
100+
body.put("Value", SecretDetector.maskJsonObject(value));
101+
return this;
102+
}
103+
104+
public LogBuilder withValue(JSONArray value) {
105+
body.put("Value", SecretDetector.maskJsonArray(value));
106+
return this;
107+
}
108+
109+
public TelemetryEvent build() {
110+
TelemetryEvent event = super.build();
111+
event.put("Type", Type.Log);
112+
return event;
113+
}
114+
}
115+
116+
private static class Builder<T> {
117+
protected final Class<T> builderClass;
118+
protected TelemetryEvent body = new TelemetryEvent();
119+
protected HashMap<String, String> tags = new HashMap<>();
120+
private static final String version =
121+
ResourceBundleManager.getSingleton(
122+
"net.snowflake.ingest.streaming.internal.fileTransferAgent.version")
123+
.getLocalizedMessage("version");
124+
private static final String driver = "JDBC";
125+
126+
public Builder(Class<T> builderClass) {
127+
this.builderClass = builderClass;
128+
withTag("driver", driver);
129+
withTag("version", version);
130+
TelemetryService instance = TelemetryService.getInstance();
131+
withTag("telemetryServerDeployment", instance.getServerDeploymentName());
132+
withTag("connectionString", instance.getDriverConnectionString());
133+
JSONObject context = instance.getContext();
134+
if (context != null) {
135+
for (String key : context.keySet()) {
136+
Object val = context.get(key);
137+
if (val != null) {
138+
withTag(
139+
"ctx_" + key.toLowerCase(), SecretDetector.maskParameterValue(key, val.toString()));
140+
}
141+
}
142+
}
143+
}
144+
145+
public T withName(String name) {
146+
body.put("Name", SecretDetector.maskSecrets(name));
147+
return builderClass.cast(this);
148+
}
149+
150+
public T withTag(String name, int value) {
151+
return withTag(name, Integer.toString(value));
152+
}
153+
154+
public T withTag(String name, String value) {
155+
if (value != null && value.length() > 0) {
156+
tags.put(name, SecretDetector.maskSecrets(value));
157+
}
158+
return builderClass.cast(this);
159+
}
160+
161+
protected TelemetryEvent build() {
162+
body.put("UUID", UUIDUtils.getUUID().toString());
163+
body.put("Created_On", SFTimestamp.getUTCNow());
164+
body.put("SchemaVersion", schemaVersion);
165+
this.putMap("Tags", tags);
166+
return body;
167+
}
168+
169+
private void putMap(String name, HashMap<String, String> map) {
170+
JSONObject tags = new JSONObject();
171+
for (String key : map.keySet()) {
172+
tags.put(key, map.get(key));
173+
}
174+
body.put(name, tags);
175+
}
176+
}
177+
178+
/**
179+
* @return the deployment of this event
180+
*/
181+
public String getDeployment() {
182+
JSONArray tags = (JSONArray) this.get("Tags");
183+
for (Object tag : tags) {
184+
JSONObject json = (JSONObject) tag;
185+
if (json.get("Name").toString().compareTo("deployment") == 0) {
186+
return json.get("Value").toString();
187+
}
188+
}
189+
return "Unknown";
190+
}
191+
}

0 commit comments

Comments
 (0)