Skip to content

Commit

Permalink
Kpg/crashlytics test stubs (#176)
Browse files Browse the repository at this point in the history
* Test new memory model

* 1 build

* Add mavenCentral to plugin repo

* Adding 1.6.0 build

* Remove windows for build tests. 1.6.0 includes windows build

* Whoops. Removed to copy for slide.

* Move to Xcode 12.5

* Found a bug

* Add docs

* Fixed clang args
  • Loading branch information
kpgalligan authored Oct 30, 2021
1 parent e62f96d commit 3db5911
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 13 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ platform that has interop with Kotlin. For iOS and Swift-specific considerations

There are multiple sample apps showing various configurations.

## Crash Reporting

Kermit includes crash reporting implementations for Crashlytics and Bugsnag. These will write breadcrumb statements to
those crash reporting tools, and can be triggered to report unhandled crash reports when there's an uncaught Kotlin
exception.

**Note: ** Crash reporter integration currently only supports static frameworks. Dynamic frameworks create linking issues,
so you'll need to add implementations directly to your source. See the documentation for more info.

## Kermit Chisel

For some situations, disabling logging is desirable. For example, when building release versions of apps. You can disable
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

buildscript {
extra["kotlin_plugin_id"] = "co.touchlab.kermit"
val KOTLIN_VERSION: String by project
dependencies {
classpath("com.vanniktech:gradle-maven-publish-plugin:0.18.0")
classpath("co.touchlab:cklib-gradle-plugin:${KOTLIN_VERSION}.4")
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/configure-crash-logger.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ kotlin {
].forEach { target ->
target.compilations.main.cinterops.create(project.name) {
includeDirs("$projectDir/src/include")
compilerOpts("-DNS_FORMAT_ARGUMENT(A)=")
compilerOpts("-DNS_FORMAT_ARGUMENT(A)=", "-D_Nullable_result=_Nullable")
if (printCInteropKotlin) {
extraOpts = listOf("-mode", "sourcecode")
}
Expand Down
17 changes: 17 additions & 0 deletions kermit-crashlytics-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# kermit-crashlytics-test

This is a stub library to use for testing if you are using `kermit-crashlytics` in your build and want to run Kotlin
tests. `kermit-crashlytics` defines the cinterop for Crashlytics, but does not provide the implementation. When you
build your final application, your final link will include Crashlytics definitions. That works if you don't run
Kotlin/Native tests. If you do, you'll get linker errors when those tests are being built.

To avoid those errors, include `kermit-crashlytics-test` in your Kotlin/Native test dependencies.

```kotlin
sourceSets["iosTest"].dependencies {
implementation("co.touchlab:kermit-crashlytics-test:x.y.z")
}
```

These stubs don't actually work, but they'll satisfy the linker so you can run your Kotlin build tests. When your
framework is built into an app, you'll need to supply the Crashlytics implementation.
80 changes: 80 additions & 0 deletions kermit-crashlytics-test/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2021 Touchlab
* 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.
*/

plugins {
kotlin("multiplatform")
id("co.touchlab.cklib")
}

val CRASHKIOS_CORE_VERSION: String by project
val CRASHLYTICS_ANDROID_VERSION: String by project


kotlin {

macosX64()
macosArm64()
iosX64()
iosArm64()
// iosArm32()
iosSimulatorArm64()
tvosArm64()
tvosSimulatorArm64()
tvosX64()
watchosArm32()
watchosArm64()
watchosSimulatorArm64()
watchosX86()
watchosX64()

sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
}

val commonTest by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-test-common")
implementation("org.jetbrains.kotlin:kotlin-test-annotations-common")
}
}

val darwinMain by creating
darwinMain.dependsOn(commonMain)

val darwinTest by creating
darwinTest.dependsOn(commonTest)

targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
val main by compilations.getting
main.defaultSourceSet.dependsOn(darwinMain)
val test by compilations.getting
test.defaultSourceSet.dependsOn(darwinTest)
}
}
}

cklib {
create("objcsample") {
language = co.touchlab.cklib.gradle.CompileToBitcode.Language.OBJC
compilerArgs.addAll(
listOf(
"-DKONAN_MI_MALLOC=1", "-DNS_FORMAT_ARGUMENT(A)=", "-D_Nullable_result=_Nullable"
)
)
}
}

apply(from = "../gradle/gradle-mvn-mpp-push.gradle")
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2021 Touchlab
* 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 co.touchlab.kermit.crashlytics

class Dummy {
}
25 changes: 25 additions & 0 deletions kermit-crashlytics-test/src/objcsample/cpp/FIRCrashlytics.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Created by Kevin Galligan on 10/11/21.
//

#import "crashlytics.h"


@implementation FIRCrashlytics
+ (instancetype)crashlytics {
return [[FIRCrashlytics alloc] init];
}

- (void)log:(NSString *)msg {

}

- (void)setCustomValue:(id)value forKey:(NSString *)key {

}

- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel {

}

@end
17 changes: 17 additions & 0 deletions kermit-crashlytics-test/src/objcsample/cpp/FIRExceptionModel.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Created by Kevin Galligan on 10/11/21.
//

#import "FIRExceptionModel.h"


@implementation FIRExceptionModel
- (instancetype)init {
return nil;
}

+ (instancetype)exceptionModelWithName:(NSString *)name reason:(NSString *)reason {
return nil;
}

@end
13 changes: 13 additions & 0 deletions kermit-crashlytics-test/src/objcsample/cpp/FIRStackFrame.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Created by Kevin Galligan on 10/11/21.
//

#import "FIRStackFrame.h"


@implementation FIRStackFrame
+ (instancetype)stackFrameWithAddress:(NSUInteger)address {
return nil;
}

@end
49 changes: 49 additions & 0 deletions kermit-crashlytics-test/src/objcsample/headers/FIRExceptionModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2020 Google LLC
//
// 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.

#import <Foundation/Foundation.h>

#import "FIRStackFrame.h"

NS_ASSUME_NONNULL_BEGIN

/**
* The Firebase Crashlytics Exception Model provides a way to report custom exceptions
* to Crashlytics that came from a runtime environment outside of the native
* platform Crashlytics is running in.
*/
NS_SWIFT_NAME(ExceptionModel)
@interface FIRExceptionModel : NSObject

/** :nodoc: */
- (instancetype)init NS_UNAVAILABLE;

/**
* Creates an Exception Model model with the given required fields.
*
* @param name - typically the type of the Exception class
* @param reason - the human-readable reason the issue occurred
*/
+ (instancetype)exceptionModelWithName:(NSString *)name
reason:(NSString *)reason NS_SWIFT_UNAVAILABLE("");

/**
* A list of Stack Frames that make up the stack trace. The order of the stack trace is top-first,
* so typically the "main" function is the last element in this list.
*/
@property(nonatomic, copy) NSArray<FIRStackFrame *> *stackTrace;

@end

NS_ASSUME_NONNULL_END
41 changes: 41 additions & 0 deletions kermit-crashlytics-test/src/objcsample/headers/FIRStackFrame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2020 Google LLC
//
// 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.

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
* The Firebase Crashlytics Stack Frame provides a way to construct the lines of
* a stack trace for reporting along with a recorded Exception Model.
*/
NS_SWIFT_NAME(StackFrame)
@interface FIRStackFrame : NSObject

/** :nodoc: */
- (instancetype)init NS_UNAVAILABLE;

/**
* Creates a symbolicated Stack Frame from an address. The address will be
* symbolicated in the Crashlytics backend for the customer and reported in the
* Crahslytics dashboard with the appropriate file name and line number. If an
* invalid address is provided it will appear in the dashboard as missing.
*
* @param address - the address where the exception occurred
*/
+ (instancetype)stackFrameWithAddress:(NSUInteger)address;

@end

NS_ASSUME_NONNULL_END
72 changes: 72 additions & 0 deletions kermit-crashlytics-test/src/objcsample/headers/crashlytics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2019 Google
//
// 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.

#import <Foundation/Foundation.h>

#import "FIRExceptionModel.h"

NS_ASSUME_NONNULL_BEGIN

/**
* The Firebase Crashlytics API provides methods to annotate and manage fatal and
* non-fatal reports captured and reported to Firebase Crashlytics.
*
* By default, Firebase Crashlytics is initialized with `[FIRApp configure]`.
*
* Note: The Crashlytics class cannot be subclassed. If this makes testing difficult,
* we suggest using a wrapper class or a protocol extension.
*/
NS_SWIFT_NAME(Crashlytics)
@interface FIRCrashlytics : NSObject

/**
* Accesses the singleton Crashlytics instance.
*
* @return The singleton Crashlytics instance.
*/
+ (instancetype)crashlytics NS_SWIFT_NAME(crashlytics());

/**
* Adds logging that is sent with your crash data. The logging does not appear in the
* system.log and is only visible in the Crashlytics dashboard.
*
* @param msg Message to log
*/
- (void)log:(NSString *)msg;

/**
* Sets a custom key and value to be associated with subsequent fatal and non-fatal reports.
* When setting an object value, the object is converted to a string. This is
* typically done by calling "-[NSObject description]".
*
* @param value The value to be associated with the key
* @param key A unique key
*/
- (void)setCustomValue:(id)value forKey:(NSString *)key;

/**
* Records an Exception Model described by an FIRExceptionModel object. The events are
* grouped and displayed similarly to crashes. Keep in mind that this method can be expensive.
* The total number of FIRExceptionModels that can be recorded during your app's life-cycle is
* limited by a fixed-size circular buffer. If the buffer is overrun, the oldest data is dropped.
* Exception Models are relayed to Crashlytics on a subsequent launch of your application.
*
* @param exceptionModel Instance of the FIRExceptionModel to be recorded
*/
- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel
NS_SWIFT_NAME(record(exceptionModel:));

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal class AtomicMutableLoggerConfig(logWriters: List<LogWriter>) : MutableL
override var minSeverity: Severity
get() = _minSeverity.value
set(value) {
_minSeverity.value = value
_minSeverity.value = value.freeze()
}
override var logWriterList: List<LogWriter>
get() = _loggerList.value
Expand Down
2 changes: 1 addition & 1 deletion samples/sample-bugsnag/.idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3db5911

Please # to comment.