Django logging - custom filter works for handler, but does not work for logger - python-logging

I have a custom filter like this:
proj/proj/log_utils/filters.py:
import logging
class OnlyThisSeverity(logging.Filter):
def filter(self, record):
print('levelname: {}'.format(record.levelname))
return record.levelno == logging.INFO
And Django settings look like this:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'filters': {
'only_this_severity': {
'()': 'android_blend.log_utils.filters.OnlyThisSeverity',
}
},
'loggers': {
'my_app': {
'handlers': ('console',), # 'console'
'level': 'INFO',
'propagate': False,
'filters': ['only_this_severity']
},
}
}
Inside my_app/test.py, I have a function like this:
import logging
logger = logging.getLogger(__name__)
def handle(self, *args, **kwargs):
logger.info('Reporting info......')
logger.error('Reporting error......')
If my filter works correctly, I should see only Reporting info in the console, whereas I see both lines.
So the problem is that only_this_severity filter is ignored.
However, if I move the filters inside the console handler definition, then I achieve my goal. What I am doing wrong ? I want the filter to work
for the logger my_app, and not only on handler level.
My ultimate goal is to change the custom behavour of logging lib. That is, for handlers of level 'X', I want them to respect only records of level 'X', not 'X and higher'.

Your filter seems to work correctly even with the filter added at logger level.
This is my current output:
levelname: INFO
Reporting info......
levelname: ERROR
This is showing how the code is reaching the filter in both log operations, but filtering the error record.
I think that the problem might be in the logger hierarchy. When you use your test.py as an imported module, you're not getting the 'my_app' logger, but the 'my_app.test' which does not exist.
When this happens, the core retrieves the root logger and 'propagates' the default configuration to a new logger called 'my_app.test' including it on the log hierarchy. This logger doesn't have your filter engaged.
Try forcing to get 'my_app' logger by passing its name:
import logging
logger = logging.getLogger('my_app')
def handle(self, *args, **kwargs):
logger.info('Reporting info......')
logger.error('Reporting error......')
Or you can use the root logger to define your filters and then let the application create the hierarchy for you:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'filters': {
'only_this_severity': {
'()': 'android_blend.log_utils.filters.OnlyThisSeverity',
}
},
'loggers': {
'root': {
'handlers': ('console',), # 'console'
'level': 'INFO',
'filters': ['only_this_severity']
},
}
}
I personally like this method because allows to safely call
logger = logging.getLogger(__name__)
in your modules in order to show (with the proper formatter) the module from which you are logging.
From https://docs.python-guide.org/writing/logging/
Best practice when instantiating loggers in a library is to only
create them using the __name__ global variable: the logging module
creates a hierarchy of loggers using dot notation, so using __name__
ensures no name collisions.

Related

How to use vue component across multiple node projects?

I'm trying to build a website builder within the drag-and-drop abilities via using Vue3. So, the user will be playing with the canvas and generate a config structure that going to post the backend. Furthermore, the server-side will generate static HTML according to this config.
Eventually, the config will be like the below and it works perfectly. The config only can have HTML tags and attributes currently. Backend uses h() function to generate dom tree.
My question is: can I use .vue component that will generate on the server side as well? For example, the client-side has a Container.vue file that includes some interactions, styles, etc. How can the backend recognize/resolve this vue file?
UPDATE:
Basically, I want to use the Vue component that exists on the Client side on the backend side to generate HTML strings same as exactly client side. (including styles, interactions etc).
Currently, I'm able to generate HTML string via the below config but want to extend/support Vue component itself.
Note: client and server are completely different projects. Currently, server takes config and runs createSSRApp, renderToString methods.
Here is the gist of how server would handle the API:
https://gist.github.com/yulafezmesi/162eafcf7f0dcb3cb83fb822568a6126
{
id: "1",
tagName: "main",
root: true,
type: "container",
properties: {
class: "h-full",
style: {
width: "800px",
transform: "translateZ(0)",
},
},
children: [
{
id: "9",
type: "image",
tagName: "figure",
interactive: true,
properties: {
class: "absolute w-28",
style: {
translate: "63px 132px",
},
},
},
],
}
This might get you started: https://vuejs.org/guide/scaling-up/ssr.html#rendering-an-app
From the docs:
// this runs in Node.js on the server.
import { createSSRApp } from 'vue'
// Vue's server-rendering API is exposed under `vue/server-renderer`.
import { renderToString } from 'vue/server-renderer'
const app = createSSRApp({
data: () => ({ count: 1 }),
template: `<button #click="count++">{{ count }}</button>`
})
renderToString(app).then((html) => {
console.log(html)
})
I guess extract the template from request or by reading the submitted Vue file and use that as the template parameter value

How to configure gtm to track OrderPlacedEvent in SAP-Spartacus?

I am using Spartacus 4.2 and i am tracking a bunch of events via GTM.
I have configured gtm to track some custom and standard events but when i try to add the OrderPlacedEvent i get the following error:
Type 'TmsConfig' has no properties in common with type 'Config'
The import for OrderPlacedEvent looks like this:
import { OrderPlacedEvent } from '#spartacus/checkout/root';
GTM-Configuration:
provideConfig({
tagManager: {
gtm: {
dynamicConfiguration: true,
// TODO: Add events for tracking here
events: [
NavigationEvent,
OrderPlacedEvent,
//... (custom Events)
],
debug: true,
},
},
} as TmsConfig),
Does anybody know what im doing wrong?
I've faced a similar problem. The reason was that some feature module was referenced before the #spartacus/core and it messed up the Config type augmentation.
You need to check if some feature module doesn't get imported before #spartacus/core. For instance in app.module.ts.

Service Workers with Vue and Bundling

I use Vue 2 with Common.js to generate an AMD Bundle. I need to be able to automatically register my service worker on runtime. Something that works:
https://www.npmjs.com/package/worker-plugin
https://www.npmjs.com/package/worker-loader
The reason I need a service worker is for sending notifications. However, I am having trouble with this, as it seems that the only workers supported are in DedicatedWorkerGlobalScope or SharedWorkers. In order to dispatch "showNotification" however, I need the Service Worker type.
So basically what I do:
import Worker from "worker-loader!./Worker.js"
const worker = new Worker()
Works like charm, as does this (Worker Plugin):
const worker = new Worker('./worker.js', { type: 'module' });
However, always normal workers. Those arent service workers and I have been trying to figure this out since hours. Is there a configuration im missing to change the type? Some insight would be great.
To illustrate what im trying to achieve:
Registration of the Service Worker needs to happen automatically on Runtime, without me having to reference absolute or relative urls.
Any insight on how I can achieve what im trying to accomplish?
I did not use your plugins but I used workbox plugin for Vue. The configuration is quite simple and well documented.
Installing in an Already Created Project
vue add workbox-pwa
Config example
// Inside vue.config.js
module.exports = {
// ...other vue-cli plugin options...
pwa: {
name: 'My App',
themeColor: '#4DBA87',
msTileColor: '#000000',
appleMobileWebAppCapable: 'yes',
appleMobileWebAppStatusBarStyle: 'black',
manifestOptions: {
start_url: '/'
},
// configure the workbox plugin
workboxPluginMode: 'GenerateSW', // 'GenerateSW' will lead to a new service worker file being created each time you rebuild your web app.
workboxOptions: {
swDest: 'service-worker.js'
}
}
}
You could use service-worker-loader instead (which is based on worker-loader).
Install service-worker-loader:
npm i -D service-worker-loader
Create a service worker script (e.g., at ./src/sw.js) with the following example contents:
import { format } from 'date-fns'
self.addEventListener('install', () => {
console.log('Service worker installed', format(new Date(), `'Today is a' eeee`))
})
Import the service worker script in your entry file:
// main.js
import registerServiceWorker from 'service-worker-loader!./sw'
registerServiceWorker({ scope: '/' }).then(registration => {
//...
registration.showNotification('Notification Title', {
body: 'Hello world!',
})
})
demo

Data Testing in EmberJS and QUnit using fixtures

I have a simple ember application and I want to test it, without making server for API calls.
I've looked around a bunch and found this piece of code which helps tremendously. Problem is for testing I want to use the fixture adapter (makes sense, right?)
#store = Lfg.__container__.lookup('store:main')
Here is my model:
Lfg.Activity = DS.Model.extend
title: DS.attr('string')
people: DS.attr('number')
maxPeople: DS.attr('number')
host: DS.attr('string')
Then inside an Em.run => I do this
Lfg.reset()
container = new Ember.Container()
# These are my models... just one for now.
[
'activity'
].forEach (x,i) ->
container.register 'model:'+x, Lfg.get( Ember.String.classify(x) )
# It's essentially just: container.register("model:activity", Lfg.Activity)
#store = DS.Store.create
adapter: DS.FixtureAdapter.extend()
container: container
But I keep getting errors with the serializer. I tried adding the serializer but doesn't help. Do I need to container.register other things as well?
The error I get is TypeError: Cannot call method 'serialize' of undefined coming from mockJSON method, more specifically store.serializerFor(type) is returning null.
If I set store via store = Lfg.__container__.lookup('store:main') and then store.serializerFor(Lfg.Activity) it seems to work ok in the console -- is this not the same store? I want to use the one with the fixture adapter. I tried setting the serializer but that didn't help.
I prefer using something like mockjax to mock the api endpoints, then using qunit and the built in helpers provided by Ember and qunit
Here's an example of how to set up a simple json response
$.mockjax({
url: '/colors',
dataType: 'json',
responseText: {
colors:[
{
id: 1,
color: "red"
},
{
id: 2,
color: "green"
},
{
id: 3,
color: "blue"
}
]
}
});
And a test that would hit this endpoint
test("root lists 3 colors", function(){
var store = App.__container__.lookup('store:main');
var colors = store.find('color');
stop();
colors.then(function(arr){
start();
equal(arr.get('length'), 3, 'store returns 3 records');
});
});
http://emberjs.jsbin.com/wipo/3/edit

Testing ember nested routes fails

I'm using karma with qUnit (after following this tutorial) to test my Ember application. It's mostly going well, however I've run into a problem that doesn't make sense.
Given the 2 following tests:
test('can get to products', function() {
visit('/products/')
.then(function() {
ok(find('*'));
});
});
test('can get to catalogues', function() {
visit('/products/catalogues')
.then(function() {
ok(find('*'));
});
});
The first will run fine. The test runner gets to /products and finds something.
However, the second test returns an error in the console:
Error: Assertion Failed: You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run
I turned on transition logs, and the test runner is visiting products.catalogues.index before throwing the error.
Any ideas with this? Or is it simply a bug inside ember's testing tools?
Both are valid routes defined inside the router...
The last part of the error holds the key to how to fix this problem. You have to make sure that any code that make async calls is wrapped in Ember.run. This includes things as simple as the create and set methods.
If you have something like
App.ProductsRoute = Ember.Route.extend({
model: function() {
return [
Ember.Object.create({title: "product1"}),
Ember.Object.create({title: "product2"})
]
}
});
refactor it to
App.ProductsRoute = Ember.Route.extend({
model: function() {
return [
Ember.run( Ember.Object, "create", {title: "product1"} ),
Ember.run( Ember.Object, "create", {title: "product2"} )
]
}
});
or
App.ProductsRoute = Ember.Route.extend({
model: function() {
return Ember.run(function() {
return [
Ember.Object.create({title: "product1"}),
Ember.Object.create({title: "product2"})
]
});
}
});
If you posted your /products code it would be easier to give a more specific answer.