Skip to content

Commit

Permalink
Add carrier information to spans (#358)
Browse files Browse the repository at this point in the history
* overload constructor for null

* Add CarrierFinder and add Carrier to CurrentNetwork.

* spotless

* relax Q to P

* add builder for CurrentNetwork

* change type and eliminate double null check

* rename class to match version 28

* set NET_HOST_CONNECTION_TYPE in common method

* change optional to null

* regen tostring

* address review suggestions

* fix test NPE

* remove unused constructor
  • Loading branch information
breedx-splk authored Sep 26, 2022
1 parent c6bbbf4 commit d237fc1
Show file tree
Hide file tree
Showing 19 changed files with 585 additions and 235 deletions.
123 changes: 123 additions & 0 deletions splunk-otel-android/src/main/java/com/splunk/rum/Carrier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright Splunk Inc.
*
* 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 com.splunk.rum;

import android.os.Build;
import android.telephony.TelephonyManager;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import java.util.Objects;

@RequiresApi(api = Build.VERSION_CODES.P)
class Carrier {

private final int id;
private final @Nullable String name;
private final @Nullable String mobileCountryCode; // 3 digits
private final @Nullable String mobileNetworkCode; // 2 or 3 digits
private final @Nullable String isoCountryCode;

static Builder builder() {
return new Builder();
}

Carrier(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.mobileCountryCode = builder.mobileCountryCode;
this.mobileNetworkCode = builder.mobileNetworkCode;
this.isoCountryCode = builder.isoCountryCode;
}

int getId() {
return id;
}

@Nullable
String getName() {
return name;
}

@Nullable
String getMobileCountryCode() {
return mobileCountryCode;
}

@Nullable
String getMobileNetworkCode() {
return mobileNetworkCode;
}

@Nullable
String getIsoCountryCode() {
return isoCountryCode;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Carrier carrier = (Carrier) o;
return id == carrier.id
&& Objects.equals(name, carrier.name)
&& Objects.equals(mobileCountryCode, carrier.mobileCountryCode)
&& Objects.equals(mobileNetworkCode, carrier.mobileNetworkCode)
&& Objects.equals(isoCountryCode, carrier.isoCountryCode);
}

@Override
public int hashCode() {
return Objects.hash(id, name, mobileCountryCode, mobileNetworkCode, isoCountryCode);
}

static class Builder {
private int id = TelephonyManager.UNKNOWN_CARRIER_ID;
private @Nullable String name = null;
private @Nullable String mobileCountryCode = null;
private @Nullable String mobileNetworkCode = null;
private @Nullable String isoCountryCode = null;

Carrier build() {
return new Carrier(this);
}

Builder id(int id) {
this.id = id;
return this;
}

Builder name(String name) {
this.name = name;
return this;
}

Builder mobileCountryCode(String countryCode) {
this.mobileCountryCode = countryCode;
return this;
}

Builder mobileNetworkCode(String networkCode) {
this.mobileNetworkCode = networkCode;
return this;
}

Builder isoCountryCode(String isoCountryCode) {
this.isoCountryCode = isoCountryCode;
return this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright Splunk Inc.
*
* 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 com.splunk.rum;

import android.os.Build;
import android.telephony.TelephonyManager;
import androidx.annotation.RequiresApi;

@RequiresApi(api = Build.VERSION_CODES.P)
class CarrierFinder {

private final TelephonyManager telephonyManager;

CarrierFinder(TelephonyManager telephonyManager) {
this.telephonyManager = telephonyManager;
}

Carrier get() {
Carrier.Builder builder = Carrier.builder();
int id = telephonyManager.getSimCarrierId();
builder.id(id);
CharSequence name = telephonyManager.getSimCarrierIdName();
if (validString(name)) {
builder.name(name.toString());
}
String simOperator = telephonyManager.getSimOperator();
if (validString(simOperator) && simOperator.length() >= 5) {
String countryCode = simOperator.substring(0, 3);
String networkCode = simOperator.substring(3);
builder.mobileCountryCode(countryCode).mobileNetworkCode(networkCode);
}
String isoCountryCode = telephonyManager.getSimCountryIso();
if (validString(isoCountryCode)) {
builder.isoCountryCode(isoCountryCode);
}
return builder.build();
}

private boolean validString(CharSequence str) {
return !(str == null || str.length() == 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
class ConnectionUtil {

static final CurrentNetwork NO_NETWORK =
new CurrentNetwork(NetworkState.NO_NETWORK_AVAILABLE, null);
CurrentNetwork.builder(NetworkState.NO_NETWORK_AVAILABLE).build();
static final CurrentNetwork UNKNOWN_NETWORK =
new CurrentNetwork(NetworkState.TRANSPORT_UNKNOWN, null);
CurrentNetwork.builder(NetworkState.TRANSPORT_UNKNOWN).build();

private final NetworkDetector networkDetector;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@

package com.splunk.rum;

import android.os.Build;
import androidx.annotation.Nullable;
import java.util.Objects;
import java.util.Optional;

final class CurrentNetwork {
@Nullable private final Carrier carrier;
private final NetworkState state;
@Nullable private final String subType;

CurrentNetwork(NetworkState state, @Nullable String subType) {
this.state = state;
this.subType = subType;
private CurrentNetwork(Builder builder) {
this.carrier = builder.carrier;
this.state = builder.state;
this.subType = builder.subType;
}

boolean isOnline() {
Expand All @@ -37,29 +39,92 @@ NetworkState getState() {
return state;
}

Optional<String> getSubType() {
return Optional.ofNullable(subType);
@Nullable
String getSubType() {
return subType;
}

@Override
public String toString() {
return "CurrentNetwork{" + "state=" + state + ", subType='" + subType + '\'' + '}';
return "CurrentNetwork{"
+ "carrier="
+ carrier
+ ", state="
+ state
+ ", subType='"
+ subType
+ '\''
+ '}';
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CurrentNetwork)) {
return false;
}
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CurrentNetwork that = (CurrentNetwork) o;
return state == that.state && Objects.equals(subType, that.subType);
return Objects.equals(carrier, that.carrier)
&& state == that.state
&& Objects.equals(subType, that.subType);
}

@Override
public int hashCode() {
return Objects.hash(state, subType);
return Objects.hash(carrier, state, subType);
}

@SuppressWarnings("NullAway")
@Nullable
public String getCarrierCountryCode() {
return haveCarrier() ? carrier.getMobileCountryCode() : null;
}

@SuppressWarnings("NullAway")
@Nullable
public String getCarrierIsoCountryCode() {
return haveCarrier() ? carrier.getIsoCountryCode() : null;
}

@SuppressWarnings("NullAway")
@Nullable
public String getCarrierNetworkCode() {
return haveCarrier() ? carrier.getMobileNetworkCode() : null;
}

@SuppressWarnings("NullAway")
@Nullable
public String getCarrierName() {
return haveCarrier() ? carrier.getName() : null;
}

private boolean haveCarrier() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) && (carrier != null);
}

static Builder builder(NetworkState state) {
return new Builder(state);
}

static class Builder {
@Nullable private Carrier carrier;
private final NetworkState state;
@Nullable private String subType;

public Builder(NetworkState state) {
this.state = state;
}

CurrentNetwork build() {
return new CurrentNetwork(this);
}

public Builder carrier(@Nullable Carrier carrier) {
this.carrier = carrier;
return this;
}

public Builder subType(@Nullable String subType) {
this.subType = subType;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ static NetworkDetector create(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return new PostApi29NetworkDetector(connectivityManager, telephonyManager, context);
CarrierFinder carrierFinder = new CarrierFinder(telephonyManager);
return new PostApi28NetworkDetector(
connectivityManager, telephonyManager, carrierFinder, context);
}
return new SimpleNetworkDetector(connectivityManager);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.concurrent.atomic.AtomicBoolean;

class NetworkMonitor implements AppStateListener {
Expand Down Expand Up @@ -78,19 +77,10 @@ public void onAvailable(boolean deviceIsOnline, CurrentNetwork activeNetwork) {
Span available =
tracer.spanBuilder("network.change")
.setAttribute(NETWORK_STATUS_KEY, "available")
.startSpan()
// put these after span start to override what might be set in the
// RumAttributeAppender.
.setAttribute(
NET_HOST_CONNECTION_TYPE,
activeNetwork.getState().getHumanName());
activeNetwork
.getSubType()
.ifPresent(
subType ->
available.setAttribute(
SemanticAttributes.NET_HOST_CONNECTION_SUBTYPE,
subType));
.startSpan();
// put these after span start to override what might be set in the
// RumAttributeAppender.
RumAttributeAppender.appendNetworkAttributes(available, activeNetwork);
available.end();
}
}
Expand Down
Loading

0 comments on commit d237fc1

Please sign in to comment.