Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport NR-234826 #335

Open
wants to merge 9 commits into
base: staging
Choose a base branch
from
87 changes: 87 additions & 0 deletions .github/workflows/branchBuild.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: BespokeBuild
on:
workflow_dispatch:
# The input version number (ex: 7.4.0) and branch are required for the bespoke branch build. Branch is an automatically added selector for all github actions.
inputs:
version:
required: true

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
deployS3:
name: DeployS3
# runs-on: will be set to macos-latest when running on actual GHA.
# *** runs-on: ubuntu-latest is used when running via act on mac os. ***
runs-on: macos-latest
outputs:
version: ${{ steps.setOutput.outputs.version }}
steps:
- uses: actions/checkout@v3
with:
submodules: true

- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '15.4'

- name: Install the Apple certificate and provisioning profile
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
# BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
# echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH

# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH

# # apply provisioning profile
# mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
# cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles

- name: Update gem
run: bundle update

- name: Install gems
run: bundle install

- name: Build NewRelic.xcframework (using fastlane)
run: bundle exec fastlane buildAndZip

- name: Get name
run: echo "version=$(cat fastlane/build_version)" >> $GITHUB_ENV

- id: setOutput
name: Print name
run: echo "version=${{ env.version }}" >> $GITHUB_OUTPUT

- name: Deploy to staging S3
run: "aws s3 cp NewRelic_XCFramework_Agent_${{ env.version }}.zip s3://nr-downloads-main/ios-v5/"
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}

- name: Upload build reports
if: failure() && steps.build-step.outcome != 'success'
uses: actions/upload-artifact@v3
with:
name: build-reports
path: /Users/runner/Library/Logs/fastlane/xcbuild/
88 changes: 49 additions & 39 deletions Agent/Instrumentation/NSURLSession/NRMAURLSessionOverride.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@

void NRMA__instanceSwizzleIfNotSwizzled(Class clazz, SEL selector, IMP newImplementation);

@interface PayloadHolder : NSObject
@property (nonatomic, retain) NRMAPayloadContainer *cppPayload;
@end

@implementation PayloadHolder
@end

@interface NRMAIMPContainer : NSObject
@property(readonly) IMP imp;
- (instancetype) initWithImp:(IMP)imp;
Expand Down Expand Up @@ -208,13 +215,12 @@ + (void)swizzleURLSessionTask
IMP originalImp = NRMAOriginal__dataTaskWithRequest;

NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:request];
NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];

NSURLSessionTask* task = ((id(*)(id,SEL,NSURLRequest*))originalImp)(self,_cmd,request);

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];


NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];

// Try to override the methods of the private class that is returned by this method.
[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];

Expand Down Expand Up @@ -243,31 +249,30 @@ + (void)swizzleURLSessionTask
}

NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:request];
NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
__block NSURLSessionTask* task = nil;

PayloadHolder *payloadHolder = [[PayloadHolder alloc] init];
payloadHolder.cppPayload = ([NRMAHTTPUtilities addConnectivityHeader:mutableRequest]);

if (completionHandler == nil) {
task = ((id(*)(id,SEL,NSURLRequest*,void(^)(NSData*,NSURLResponse*,NSError*)))originalImp)(self,_cmd,mutableRequest,completionHandler);

NSURLSessionDataTask* task = ((id(*)(id,SEL,NSURLRequest*,void(^)(NSData*,NSURLResponse*,NSError*)))originalImp)(self,_cmd,mutableRequest,completionHandler);

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];
[NRMAHTTPUtilities attachPayload:payloadHolder.cppPayload to:task.originalRequest];

[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];
return task;
}

__block NSURLSessionTask* task = nil;

task = ((id(*)(id,SEL,NSURLRequest*,void(^)(NSData*,NSURLResponse*,NSError*)))originalImp)(self,_cmd,mutableRequest,^(NSData* data, NSURLResponse* response, NSError* error){

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];
[NRMAHTTPUtilities attachPayload:payloadHolder.cppPayload to:task.originalRequest];

NRMA__recordTask(task,data,response,error);

completionHandler(data,response,error);
});


// Try to override the methods of the private class that is returned by this method.
[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];

Expand Down Expand Up @@ -306,11 +311,11 @@ + (void)swizzleURLSessionTask
}

NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:request];
NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
NSURLSessionTask* task = ((NSURLSessionTask*(*)(id,SEL,NSURLRequest*,NSURL*))originalImp)(self,_cmd,mutableRequest,fileURL);

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];
NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];

[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];

Expand All @@ -329,11 +334,9 @@ + (void)swizzleURLSessionTask
}

NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:request];

NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];

NSURLSessionTask* task = ((NSURLSessionTask*(*)(id,SEL,NSURLRequest*,NSData*))originalImp)(self, _cmd, mutableRequest, data);

NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
[NRMAHTTPUtilities attachPayload:payload to:task.originalRequest];

[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];
Expand Down Expand Up @@ -370,29 +373,32 @@ + (void)swizzleURLSessionTask
}

NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:request];
NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
__block NSURLSessionUploadTask* task = nil;
PayloadHolder *payloadHolder = [[PayloadHolder alloc] init];

payloadHolder.cppPayload = ([NRMAHTTPUtilities addConnectivityHeader:mutableRequest]);

if (completionHandler == nil) {
NSURLSessionUploadTask* task = ((NSURLSessionUploadTask*(*)(id,SEL,NSURLRequest*,NSURL*,void(^)(NSData*,NSURLResponse*,NSError*)))originalIMP)(self,_cmd,mutableRequest,fileURL,completionHandler);
task = ((NSURLSessionUploadTask*(*)(id,SEL,NSURLRequest*,NSURL*,void(^)(NSData*,NSURLResponse*,NSError*)))originalIMP)(self,_cmd,mutableRequest,fileURL,completionHandler);


[NRMAHTTPUtilities attachPayload:payloadHolder.cppPayload to:task.originalRequest];

[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];
[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];
return task;
}

__block NSURLSessionUploadTask* task = nil;

task = ((NSURLSessionUploadTask*(*)(id,SEL,NSURLRequest*,NSURL*,void(^)(NSData*,NSURLResponse*,NSError*)))originalIMP)(self,_cmd,mutableRequest,fileURL,^(NSData* data,
NSURLResponse* response,
NSError* error){

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];
[NRMAHTTPUtilities attachPayload:payloadHolder.cppPayload to:task.originalRequest];

NRMA__recordTask(task,data,response,error);

completionHandler(data,response,error);
});

// Try to override the methods of the private class that is returned by this method.
[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];
return task;
Expand All @@ -410,28 +416,32 @@ + (void)swizzleURLSessionTask
}

NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:request];
NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
__block NSURLSessionUploadTask* task = nil;

PayloadHolder *payloadHolder = [[PayloadHolder alloc] init];

payloadHolder.cppPayload = ([NRMAHTTPUtilities addConnectivityHeader:mutableRequest]);

if (completionHandler == nil) {
NSURLSessionUploadTask* task = ((NSURLSessionUploadTask*(*)(id,SEL,NSURLRequest*,NSData*,void(^)(NSData*,NSURLResponse*,NSError*)))originalIMP)(self,_cmd,mutableRequest,bodyData,completionHandler);
task = ((NSURLSessionUploadTask*(*)(id,SEL,NSURLRequest*,NSData*,void(^)(NSData*,NSURLResponse*,NSError*)))originalIMP)(self,_cmd,mutableRequest,bodyData,completionHandler);

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];

[NRMAHTTPUtilities attachPayload:payloadHolder.cppPayload to:task.originalRequest];

[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];
return task;
}

__block NSURLSessionUploadTask* task = nil;

task = ((NSURLSessionUploadTask*(*)(id,SEL,NSURLRequest*,NSData*,void(^)(NSData*,NSURLResponse*,NSError*)))originalIMP)(self,_cmd,mutableRequest,bodyData,^(NSData* data, NSURLResponse* response, NSError* error){

[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];

[NRMAHTTPUtilities attachPayload:payloadHolder.cppPayload to:task.originalRequest];

NRMA__recordTask(task,data,response,error);

completionHandler(data,response,error);
});

// Try to override the methods of the private class that is returned by this method.
[NRMAURLSessionTaskOverride instrumentConcreteClass:[task class]];
return task;
Expand Down
27 changes: 15 additions & 12 deletions Agent/Instrumentation/NSURLSession/NRMAURLSessionTaskOverride.m
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ + (void) deinstrument
}
}

+ (NSInteger) statusCode:(NSURLResponse*)response {
return [response isKindOfClass:[NSHTTPURLResponse class]] ? [((NSHTTPURLResponse*)response) statusCode] : -1;
}

// Currently we support NSURLSessionDataTask, NSURLSessionDownloadTask, and NSURLSessionUploadTask.
+ (bool) isSupportedTaskType:(NSURLSessionTask*) task {
return [task isKindOfClass:[NSURLSessionDataTask class]] || [task isKindOfClass:[NSURLSessionDownloadTask class]] || [task isKindOfClass:[NSURLSessionUploadTask class]];
Expand Down Expand Up @@ -119,19 +115,26 @@ void NRMAOverride__urlSessionTask_SetState(NSURLSessionTask* task, SEL _cmd, NSU
if ([NRMAURLSessionTaskOverride isSupportedTaskType: task]) {
// Checking for NEW_RELIC_CROSS_PROCESS_ID_HEADER_KEY in the headers here. The data usually isn't link to the task yet here so, if that header exists we are handling the task elsewhere and have a better chance of getting the data so we don't need to record it here.
NSURLRequest *currentRequest = task.currentRequest;

if(currentRequest != nil && [currentRequest valueForHTTPHeaderField:NEW_RELIC_CROSS_PROCESS_ID_HEADER_KEY] != nil) {
return;
}

NSURL *url = [currentRequest URL];
if (url != nil &&
newState != NSURLSessionTaskStateRunning && task.state == NSURLSessionTaskStateRunning) {
// get response code
NSUInteger responseCode = [NRMAURLSessionTaskOverride statusCode:task.response];
if (responseCode != -1) {
NSData *data = NRMA__getDataForSessionTask(task);
NRMA__recordTask(task, data, task.response, task.error);
}
task.state == NSURLSessionTaskStateRunning) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check that the response we get is of type NSHTTPURLResponse? That is kind of what the response code check does.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed the other places we call NRMA__recordTask we don’t even care about the responseCode. I’m not sure why the NRMAURLSessionTaskOverride was checking the response code and checking that task.response was of type NSHTTPURLResponse.


// Added this section to add Distributed Tracing traceId\trace.id, guid,id and payload.
//1
NSMutableURLRequest* mutableRequest = [NRMAHTTPUtilities addCrossProcessIdentifier:currentRequest];
mutableRequest = [NRMAHTTPUtilities addConnectivityHeaderAndPayload:mutableRequest];

NRMAPayloadContainer* payload = [NRMAHTTPUtilities addConnectivityHeader:mutableRequest];
[NRMAHTTPUtilities attachPayload:payload
to:task.originalRequest];

NSData *data = NRMA__getDataForSessionTask(task);
NRMA__recordTask(task, data, task.response, task.error);
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions Agent/Network/NRMANetworkFacade.mm
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,12 @@ + (void) noticeNetworkRequest:(NSURLRequest*)request
contentType:[NRMANetworkFacade contentType:response]
bytesSent:bytesSent];
NSUInteger modifiedBytesReceived = bytesReceived;
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
NSString* header = httpResponse.allHeaderFields[@"Content-Encoding"];
if ([header isEqualToString:@"gzip"]) {
modifiedBytesReceived = [[NRMAHarvesterConnection gzipData:responseData] length];
if (([response isKindOfClass:[NSHTTPURLResponse class]])) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
NSString* header = httpResponse.allHeaderFields[@"Content-Encoding"];
if ([header isEqualToString:@"gzip"]) {
modifiedBytesReceived = [[NRMAHarvesterConnection gzipData:responseData] length];
}
}


Expand Down
18 changes: 18 additions & 0 deletions Test Harness/NRTestApp/NRTestApp/ViewModels/UtilViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ class UtilViewModel {
options.append(UtilOption(title: "Notice Network Request", handler: { [self] in noticeNWRequest()}))
options.append(UtilOption(title: "Notice Network Failure", handler: { [self] in noticeFailedNWRequest()}))
options.append(UtilOption(title: "URLSession dataTask", handler: { [self] in doDataTask()}))
options.append(UtilOption(title: "Async URLSession dataTask", handler: { [self] in
Task {
try await doAsyncDataTask()
}
}))

options.append(UtilOption(title: "Shut down New Relic Agent", handler: { [self] in shutDown()}))
}

Expand Down Expand Up @@ -157,6 +163,18 @@ class UtilViewModel {
dataTask.resume()
}

// Async
func doAsyncDataTask() async throws {
let urlSession = URLSession(configuration: URLSession.shared.configuration, delegate: taskProcessor, delegateQueue: nil)

guard let url = URL(string: "https://www.google.com") else { return }

let request = URLRequest(url: url)
let (data, _) = try await urlSession.data(for: request)

print("Data: \(data)")
}

func shutDown() {
NewRelic.shutdown()
}
Expand Down
Loading