musora-content-services 2.119.1 → 2.119.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/contentTypeConfig.js +1 -1
- package/src/services/content.js +14 -6
- package/src/services/sync/telemetry/index.ts +62 -53
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.119.2](https://github.com/railroadmedia/musora-content-services/compare/v2.119.1...v2.119.2) (2026-01-14)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* better logs in Sentry for debugging ([#712](https://github.com/railroadmedia/musora-content-services/issues/712)) ([e1019b5](https://github.com/railroadmedia/musora-content-services/commit/e1019b50b0cf606b86e71028db0a2f9ac354cfca))
|
|
11
|
+
|
|
5
12
|
### [2.119.1](https://github.com/railroadmedia/musora-content-services/compare/v2.119.0...v2.119.1) (2026-01-14)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
package/src/contentTypeConfig.js
CHANGED
|
@@ -229,7 +229,7 @@ export const lessonTypesMapping = {
|
|
|
229
229
|
performances: performancesLessonTypes,
|
|
230
230
|
'student archives': studentArchivesLessonTypes,
|
|
231
231
|
documentaries: ['documentary-lesson'],
|
|
232
|
-
courses: ['course'],
|
|
232
|
+
courses: ['course', 'course-collection'],
|
|
233
233
|
'guided courses': ['guided-course'],
|
|
234
234
|
'course collections': ['course-collection'],
|
|
235
235
|
'skill packs': ['skill-pack'],
|
package/src/services/content.js
CHANGED
|
@@ -116,7 +116,7 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
116
116
|
addProgressPercentage: true,
|
|
117
117
|
addProgressStatus: true
|
|
118
118
|
})
|
|
119
|
-
} else if (sort === 'recommended') {
|
|
119
|
+
} else if (sort === 'recommended' && tabName.toLowerCase() !== Tabs.ExploreAll.name.toLowerCase()) {
|
|
120
120
|
const contentTypes = lessonTypesMapping[tabName.toLowerCase()] || []
|
|
121
121
|
const allRecommendations = await recommendations(brand, { contentTypes, section: tabRecSysSection })
|
|
122
122
|
|
|
@@ -162,12 +162,20 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
162
162
|
})
|
|
163
163
|
} else {
|
|
164
164
|
let temp = await fetchTabData(brand, pageName, { page, limit, sort, includedFields: mergedIncludedFields, progress: progressValue });
|
|
165
|
+
const [ranking, contextResults] = await Promise.all([
|
|
166
|
+
sort === 'recommended' ? rankItems(brand, temp.entity.map(e => e.id)) : [],
|
|
167
|
+
addContextToContent(() => temp.entity, {
|
|
168
|
+
addNextLesson: true,
|
|
169
|
+
addNavigateTo: true,
|
|
170
|
+
addProgressPercentage: true,
|
|
171
|
+
addProgressStatus: true
|
|
172
|
+
})
|
|
173
|
+
]);
|
|
165
174
|
|
|
166
|
-
results =
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
addProgressStatus: true
|
|
175
|
+
results = ranking.length === 0 ? contextResults : contextResults.sort((a, b) => {
|
|
176
|
+
const indexA = ranking.indexOf(a.id);
|
|
177
|
+
const indexB = ranking.indexOf(b.id);
|
|
178
|
+
return (indexA === -1 ? Infinity : indexA) - (indexB === -1 ? Infinity : indexB);
|
|
171
179
|
})
|
|
172
180
|
}
|
|
173
181
|
|
|
@@ -2,7 +2,7 @@ import watermelonLogger from '@nozbe/watermelondb/utils/common/logger'
|
|
|
2
2
|
import { SyncError, SyncUnexpectedError } from '../errors'
|
|
3
3
|
|
|
4
4
|
import * as InjectedSentry from '@sentry/browser'
|
|
5
|
-
export type SentryBrowserOptions = NonNullable<Parameters<typeof InjectedSentry.init>[0]
|
|
5
|
+
export type SentryBrowserOptions = NonNullable<Parameters<typeof InjectedSentry.init>[0]>
|
|
6
6
|
|
|
7
7
|
export type SentryLike = {
|
|
8
8
|
captureException: typeof InjectedSentry.captureException
|
|
@@ -21,7 +21,7 @@ export enum SeverityLevel {
|
|
|
21
21
|
LOG = 2,
|
|
22
22
|
WARNING = 3,
|
|
23
23
|
ERROR = 4,
|
|
24
|
-
FATAL = 5
|
|
24
|
+
FATAL = 5,
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export class SyncTelemetry {
|
|
@@ -41,7 +41,7 @@ export class SyncTelemetry {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
private userId: string
|
|
44
|
-
private Sentry: SentryLike
|
|
44
|
+
private Sentry: SentryLike
|
|
45
45
|
private level: SeverityLevel
|
|
46
46
|
private pretty: boolean
|
|
47
47
|
|
|
@@ -50,15 +50,25 @@ export class SyncTelemetry {
|
|
|
50
50
|
// allows us to know if Sentry shouldn't double-capture a dev-prettified console.error log
|
|
51
51
|
private _ignoreConsole = false
|
|
52
52
|
|
|
53
|
-
constructor(
|
|
53
|
+
constructor(
|
|
54
|
+
userId: string,
|
|
55
|
+
{
|
|
56
|
+
Sentry,
|
|
57
|
+
level,
|
|
58
|
+
pretty,
|
|
59
|
+
}: { Sentry: SentryLike; level?: keyof typeof SeverityLevel; pretty?: boolean }
|
|
60
|
+
) {
|
|
54
61
|
this.userId = userId
|
|
55
62
|
this.Sentry = Sentry
|
|
56
|
-
this.level =
|
|
63
|
+
this.level =
|
|
64
|
+
typeof level !== 'undefined' && level in SeverityLevel
|
|
65
|
+
? SeverityLevel[level]
|
|
66
|
+
: SeverityLevel.LOG
|
|
57
67
|
this.pretty = typeof pretty !== 'undefined' ? pretty : true
|
|
58
68
|
|
|
59
|
-
watermelonLogger.log = (
|
|
60
|
-
watermelonLogger.warn = (
|
|
61
|
-
watermelonLogger.error = (
|
|
69
|
+
watermelonLogger.log = (message: unknown) => this.log(message instanceof Error ? message : ['[Watermelon]', message].join(' '))
|
|
70
|
+
watermelonLogger.warn = (message: unknown) => this.warn(message instanceof Error ? message : ['[Watermelon]', message].join(' '))
|
|
71
|
+
watermelonLogger.error = (message: unknown) => this.error(message instanceof Error ? message : ['[Watermelon]', message].join(' '))
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
trace<T>(opts: StartSpanOptions, callback: (_span: Span) => T) {
|
|
@@ -68,8 +78,8 @@ export class SyncTelemetry {
|
|
|
68
78
|
op: `${SYNC_TELEMETRY_TRACE_PREFIX}${opts.op}`,
|
|
69
79
|
attributes: {
|
|
70
80
|
...opts.attributes,
|
|
71
|
-
userId: this.userId
|
|
72
|
-
}
|
|
81
|
+
userId: this.userId,
|
|
82
|
+
},
|
|
73
83
|
}
|
|
74
84
|
return this.Sentry.startSpan<T>(options, (span) => {
|
|
75
85
|
let desc = span['_spanId'].slice(0, 4)
|
|
@@ -84,14 +94,20 @@ export class SyncTelemetry {
|
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
capture(err: Error, context = {}) {
|
|
87
|
-
const wrapped =
|
|
97
|
+
const wrapped =
|
|
98
|
+
err instanceof SyncError ? err : new SyncUnexpectedError((err as Error).message, context)
|
|
88
99
|
|
|
89
100
|
wrapped.markReported()
|
|
90
|
-
this.Sentry.captureException(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
this.Sentry.captureException(
|
|
102
|
+
err,
|
|
103
|
+
err instanceof SyncUnexpectedError
|
|
104
|
+
? {
|
|
105
|
+
mechanism: {
|
|
106
|
+
handled: false,
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
: undefined
|
|
110
|
+
)
|
|
95
111
|
|
|
96
112
|
this._ignoreConsole = true
|
|
97
113
|
this.error(err.message)
|
|
@@ -123,73 +139,66 @@ export class SyncTelemetry {
|
|
|
123
139
|
return false
|
|
124
140
|
}
|
|
125
141
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return this.shouldIgnoreMessage(message)
|
|
129
|
-
})
|
|
142
|
+
debug(message: unknown, extra?: any) {
|
|
143
|
+
this._log(SeverityLevel.DEBUG, 'info', message, extra)
|
|
130
144
|
}
|
|
131
145
|
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
this.recordBreadcrumb('debug', ...messages)
|
|
146
|
+
info(message: unknown, extra?: any) {
|
|
147
|
+
this._log(SeverityLevel.INFO, 'info', message, extra)
|
|
135
148
|
}
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
this.
|
|
139
|
-
this.recordBreadcrumb('info', ...messages)
|
|
150
|
+
log(message: unknown, extra?: any) {
|
|
151
|
+
this._log(SeverityLevel.LOG, 'log', message, extra)
|
|
140
152
|
}
|
|
141
153
|
|
|
142
|
-
|
|
143
|
-
this.
|
|
144
|
-
this.recordBreadcrumb('log', ...messages)
|
|
154
|
+
warn(message: unknown, extra?: any) {
|
|
155
|
+
this._log(SeverityLevel.WARNING, 'warn', message, extra)
|
|
145
156
|
}
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
this.recordBreadcrumb('warning', ...messages)
|
|
158
|
+
error(message: unknown[], extra?: any) {
|
|
159
|
+
this._log(SeverityLevel.ERROR, 'error', message, extra)
|
|
150
160
|
}
|
|
151
161
|
|
|
152
|
-
|
|
153
|
-
this.
|
|
154
|
-
this.recordBreadcrumb('error', ...messages)
|
|
162
|
+
fatal(message: unknown[], extra?: any) {
|
|
163
|
+
this._log(SeverityLevel.FATAL, 'error', message, extra)
|
|
155
164
|
}
|
|
156
165
|
|
|
157
|
-
|
|
158
|
-
this.level
|
|
159
|
-
this.recordBreadcrumb('fatal', ...messages)
|
|
160
|
-
}
|
|
166
|
+
_log(level: SeverityLevel, consoleMethod: 'info' | 'log' | 'warn' | 'error', message: unknown, extra?: any) {
|
|
167
|
+
if (this.level > level || this.shouldIgnoreMessage(message)) return
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
this.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
category: 'sync',
|
|
167
|
-
})
|
|
169
|
+
this._ignoreConsole = true
|
|
170
|
+
console[consoleMethod](...this.formattedConsoleMessage(message, extra))
|
|
171
|
+
this._ignoreConsole = false
|
|
172
|
+
this.Sentry.captureMessage(message instanceof Error ? message.message : String(message), level)
|
|
168
173
|
}
|
|
169
174
|
|
|
170
|
-
private
|
|
175
|
+
private formattedConsoleMessage(message: unknown, extra: any) {
|
|
171
176
|
if (!this.pretty) {
|
|
172
|
-
return
|
|
177
|
+
return [message, ...(extra ? [extra] : [])]
|
|
173
178
|
}
|
|
174
179
|
|
|
175
|
-
const date = new Date()
|
|
176
|
-
return [...this.consolePrefix(date), ...
|
|
180
|
+
const date = new Date()
|
|
181
|
+
return [...this.consolePrefix(date), message, ...(extra ? [extra] : []), ...this.consoleSuffix(date)]
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
private consolePrefix(date: Date) {
|
|
180
|
-
const now = Math.round(date.getTime() / 1000).toString()
|
|
181
|
-
return [
|
|
185
|
+
const now = Math.round(date.getTime() / 1000).toString()
|
|
186
|
+
return [
|
|
187
|
+
`📡 SYNC: (%c${now.slice(0, 5)}%c${now.slice(5, 10)})`,
|
|
188
|
+
'color: #ccc',
|
|
189
|
+
'font-weight: bold;',
|
|
190
|
+
]
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
private consoleSuffix(date: Date) {
|
|
185
|
-
return [` [${date.toLocaleTimeString()}, ${date.getTime()}]`]
|
|
194
|
+
return [` [${date.toLocaleTimeString()}, ${date.getTime()}]`]
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
private shouldIgnoreMessage(message: any) {
|
|
189
198
|
if (message instanceof Error) message = message.message
|
|
190
199
|
if (typeof message !== 'string') return false
|
|
191
200
|
|
|
192
|
-
return this.ignorePatterns.some(pattern => {
|
|
201
|
+
return this.ignorePatterns.some((pattern) => {
|
|
193
202
|
if (typeof pattern === 'string') {
|
|
194
203
|
return message.indexOf(pattern) !== -1
|
|
195
204
|
} else if (pattern instanceof RegExp) {
|